<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.sugarlabs.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fede</id>
	<title>Sugar Labs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.sugarlabs.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fede"/>
	<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/go/Special:Contributions/Fede"/>
	<updated>2026-05-14T19:08:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36523</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36523"/>
		<updated>2009-09-01T20:21:17Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* How do i remove an specific button from the toolbar? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo llamar repetidamente a un método específico después de un número N de segundos? ===&lt;br /&gt;
La función gobject.timeout_add() te permite invocar un método después de un período de tiempo determinado. Si quieres llamar a un método en varias ocasiones, simplemente sigue llamando a la función de gobject.timeout_add desde tu función.&lt;br /&gt;
El código de abajo es un ejemplo simple en donde la función que implementa el timeout se llama repeatedly_call. Nota que la sincronización entre las llamadas son aproximadas. Para que esto funcione debes llamar a repeatedly_call() desde alguna parte de tu código.&lt;br /&gt;
&lt;br /&gt;
Puedes ver un mejor ejemplo de este patrón en uso [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | aquí]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#Este método se llama a sí mismo aproximadamente cada 1 segundo&lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo actualizar la build que se ejecuta en mi XO? ===&lt;br /&gt;
&lt;br /&gt;
Hay varias páginas que te dan instrucciones sobre cómo instalar / actualizar la build actual. &lt;br /&gt;
&lt;br /&gt;
* Si usted ya tiene una build instalada y una conexión a Internet, primero pruebe usar [[OLPC: OLPC-update]].&lt;br /&gt;
* Si eso no funciona, puedes mirar las instrucciones para una [[OLPC: Activated upgrade]] que se puede hacer a través de un USB]&lt;br /&gt;
&lt;br /&gt;
Como mencionan las instrucciones en las páginas más arriba, asegurate de instalar tus actividades por separado luego de que actualices a una build específica.&lt;br /&gt;
&lt;br /&gt;
=== Estoy desarrollando en una XO pero mi teclado y la configuración de idioma no son ideales. ¿Cómo puedo cambiarlos? ===&lt;br /&gt;
&lt;br /&gt;
Las laptops intenacionalizadas tienen configuraciones que te pueden retrazar mientras estás desarrollando. Para cambiar las configuraciones de idioma usa el [[olpc:Sugar Control Panel]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Qué paquetes están disponibles dentro de Sugar para el desarrollo de juegos? ===&lt;br /&gt;
&lt;br /&gt;
Si tu actividad requiere herramientas para desarrollar juegos robustos y límpios deberías utilizar [http://www.pygame.org/ pygame]. Puedes importar el paquete para usarlo con cualqueir actividad de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo elimino un botón específico de la barra de herramientas? ===&lt;br /&gt;
&lt;br /&gt;
Aquí hay un ejemplo de como borrar el botón de compartir:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36522</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36522"/>
		<updated>2009-09-01T20:20:08Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* ¿Qué paquetes están disponibles dentro de Sugar que soportan el desarrollo de juegos? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo llamar repetidamente a un método específico después de un número N de segundos? ===&lt;br /&gt;
La función gobject.timeout_add() te permite invocar un método después de un período de tiempo determinado. Si quieres llamar a un método en varias ocasiones, simplemente sigue llamando a la función de gobject.timeout_add desde tu función.&lt;br /&gt;
El código de abajo es un ejemplo simple en donde la función que implementa el timeout se llama repeatedly_call. Nota que la sincronización entre las llamadas son aproximadas. Para que esto funcione debes llamar a repeatedly_call() desde alguna parte de tu código.&lt;br /&gt;
&lt;br /&gt;
Puedes ver un mejor ejemplo de este patrón en uso [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | aquí]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#Este método se llama a sí mismo aproximadamente cada 1 segundo&lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo actualizar la build que se ejecuta en mi XO? ===&lt;br /&gt;
&lt;br /&gt;
Hay varias páginas que te dan instrucciones sobre cómo instalar / actualizar la build actual. &lt;br /&gt;
&lt;br /&gt;
* Si usted ya tiene una build instalada y una conexión a Internet, primero pruebe usar [[OLPC: OLPC-update]].&lt;br /&gt;
* Si eso no funciona, puedes mirar las instrucciones para una [[OLPC: Activated upgrade]] que se puede hacer a través de un USB]&lt;br /&gt;
&lt;br /&gt;
Como mencionan las instrucciones en las páginas más arriba, asegurate de instalar tus actividades por separado luego de que actualices a una build específica.&lt;br /&gt;
&lt;br /&gt;
=== Estoy desarrollando en una XO pero mi teclado y la configuración de idioma no son ideales. ¿Cómo puedo cambiarlos? ===&lt;br /&gt;
&lt;br /&gt;
Las laptops intenacionalizadas tienen configuraciones que te pueden retrazar mientras estás desarrollando. Para cambiar las configuraciones de idioma usa el [[olpc:Sugar Control Panel]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Qué paquetes están disponibles dentro de Sugar para el desarrollo de juegos? ===&lt;br /&gt;
&lt;br /&gt;
Si tu actividad requiere herramientas para desarrollar juegos robustos y límpios deberías utilizar [http://www.pygame.org/ pygame]. Puedes importar el paquete para usarlo con cualqueir actividad de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36521</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36521"/>
		<updated>2009-09-01T20:19:29Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* What packages are available on sugar to support game development? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo llamar repetidamente a un método específico después de un número N de segundos? ===&lt;br /&gt;
La función gobject.timeout_add() te permite invocar un método después de un período de tiempo determinado. Si quieres llamar a un método en varias ocasiones, simplemente sigue llamando a la función de gobject.timeout_add desde tu función.&lt;br /&gt;
El código de abajo es un ejemplo simple en donde la función que implementa el timeout se llama repeatedly_call. Nota que la sincronización entre las llamadas son aproximadas. Para que esto funcione debes llamar a repeatedly_call() desde alguna parte de tu código.&lt;br /&gt;
&lt;br /&gt;
Puedes ver un mejor ejemplo de este patrón en uso [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | aquí]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#Este método se llama a sí mismo aproximadamente cada 1 segundo&lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo actualizar la build que se ejecuta en mi XO? ===&lt;br /&gt;
&lt;br /&gt;
Hay varias páginas que te dan instrucciones sobre cómo instalar / actualizar la build actual. &lt;br /&gt;
&lt;br /&gt;
* Si usted ya tiene una build instalada y una conexión a Internet, primero pruebe usar [[OLPC: OLPC-update]].&lt;br /&gt;
* Si eso no funciona, puedes mirar las instrucciones para una [[OLPC: Activated upgrade]] que se puede hacer a través de un USB]&lt;br /&gt;
&lt;br /&gt;
Como mencionan las instrucciones en las páginas más arriba, asegurate de instalar tus actividades por separado luego de que actualices a una build específica.&lt;br /&gt;
&lt;br /&gt;
=== Estoy desarrollando en una XO pero mi teclado y la configuración de idioma no son ideales. ¿Cómo puedo cambiarlos? ===&lt;br /&gt;
&lt;br /&gt;
Las laptops intenacionalizadas tienen configuraciones que te pueden retrazar mientras estás desarrollando. Para cambiar las configuraciones de idioma usa el [[olpc:Sugar Control Panel]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Qué paquetes están disponibles dentro de Sugar que soportan el desarrollo de juegos? ===&lt;br /&gt;
&lt;br /&gt;
Si tu actividad requiere herramientas para desarrollar juegos robustos y límpios deberías utilizar [http://www.pygame.org/ pygame]. Puedes importar el paquete para usarlo con cualqueir actividad de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36274</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36274"/>
		<updated>2009-08-31T22:11:35Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo llamar repetidamente a un método específico después de un número N de segundos? ===&lt;br /&gt;
La función gobject.timeout_add() te permite invocar un método después de un período de tiempo determinado. Si quieres llamar a un método en varias ocasiones, simplemente sigue llamando a la función de gobject.timeout_add desde tu función.&lt;br /&gt;
El código de abajo es un ejemplo simple en donde la función que implementa el timeout se llama repeatedly_call. Nota que la sincronización entre las llamadas son aproximadas. Para que esto funcione debes llamar a repeatedly_call() desde alguna parte de tu código.&lt;br /&gt;
&lt;br /&gt;
Puedes ver un mejor ejemplo de este patrón en uso [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | aquí]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#Este método se llama a sí mismo aproximadamente cada 1 segundo&lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo actualizar la build que se ejecuta en mi XO? ===&lt;br /&gt;
&lt;br /&gt;
Hay varias páginas que te dan instrucciones sobre cómo instalar / actualizar la build actual. &lt;br /&gt;
&lt;br /&gt;
* Si usted ya tiene una build instalada y una conexión a Internet, primero pruebe usar [[OLPC: OLPC-update]].&lt;br /&gt;
* Si eso no funciona, puedes mirar las instrucciones para una [[OLPC: Activated upgrade]] que se puede hacer a través de un USB]&lt;br /&gt;
&lt;br /&gt;
Como mencionan las instrucciones en las páginas más arriba, asegurate de instalar tus actividades por separado luego de que actualices a una build específica.&lt;br /&gt;
&lt;br /&gt;
=== Estoy desarrollando en una XO pero mi teclado y la configuración de idioma no son ideales. ¿Cómo puedo cambiarlos? ===&lt;br /&gt;
&lt;br /&gt;
Las laptops intenacionalizadas tienen configuraciones que te pueden retrazar mientras estás desarrollando. Para cambiar las configuraciones de idioma usa el [[olpc:Sugar Control Panel]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36273</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36273"/>
		<updated>2009-08-31T21:54:19Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* How do I update the current build version of code that is running on my XO? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo llamar repetidamente a un método específico después de un número N de segundos? ===&lt;br /&gt;
La función gobject.timeout_add() te permite invocar un método después de un período de tiempo determinado. Si quieres llamar a un método en varias ocasiones, simplemente sigue llamando a la función de gobject.timeout_add desde tu función.&lt;br /&gt;
El código de abajo es un ejemplo simple en donde la función que implementa el timeout se llama repeatedly_call. Nota que la sincronización entre las llamadas son aproximadas. Para que esto funcione debes llamar a repeatedly_call() desde alguna parte de tu código.&lt;br /&gt;
&lt;br /&gt;
Puedes ver un mejor ejemplo de este patrón en uso [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | aquí]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#Este método se llama a sí mismo aproximadamente cada 1 segundo&lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo actualizar la build que se ejecuta en mi XO? ===&lt;br /&gt;
&lt;br /&gt;
Hay varias páginas que te dan instrucciones sobre cómo instalar / actualizar la build actual. &lt;br /&gt;
&lt;br /&gt;
* Si usted ya tiene una build instalada y una conexión a Internet, primero pruebe usar [[OLPC: OLPC-update]].&lt;br /&gt;
* Si eso no funciona, puedes mirar las instrucciones para una [[OLPC: Activated upgrade]] que se puede hacer a través de un USB]&lt;br /&gt;
&lt;br /&gt;
Como mencionan las instrucciones en las páginas más arriba, asegurate de instalar tus actividades por separado luego de que actualices a una build específica.&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36272</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36272"/>
		<updated>2009-08-31T21:40:41Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* How do I repeatedly call a specific method after N number of seconds? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo llamar repetidamente a un método específico después de un número N de segundos? ===&lt;br /&gt;
La función gobject.timeout_add() te permite invocar un método después de un período de tiempo determinado. Si quieres llamar a un método en varias ocasiones, simplemente sigue llamando a la función de gobject.timeout_add desde tu función.&lt;br /&gt;
El código de abajo es un ejemplo simple en donde la función que implementa el timeout se llama repeatedly_call. Nota que la sincronización entre las llamadas son aproximadas. Para que esto funcione debes llamar a repeatedly_call() desde alguna parte de tu código.&lt;br /&gt;
&lt;br /&gt;
Puedes ver un mejor ejemplo de este patrón en uso [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | aquí]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#Este método se llama a sí mismo aproximadamente cada 1 segundo&lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36228</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36228"/>
		<updated>2009-08-31T16:57:17Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* How do I know the current language setting on my XO? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber la configuración actual del lenguage en mi XO? ===&lt;br /&gt;
La variable &#039;LANG&#039; te dice que lenguaje está actualmente activo en el XO. El código siguiente muestra cómo buscar en el valor de esta variable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36227</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36227"/>
		<updated>2009-08-31T16:48:50Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* How do I know whether my activity is running on a physical XO? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo saber si mi actividad se está ejecutando en una XO? ===&lt;br /&gt;
Sugar corre en PCs comunes, así como en XO. Aunque tu actuvidad probablemente corra en una XO real, algunas personas necesitan utilizarla en otros lados. Normalmente no deberías escribir una actividad que le importe si es una XO o no donde se está ejecutando. Si por alguna extraña razón necesitas saber, la forma más fácil es verificar si /sys/power/olpc-pm (el manejador de poder de la XO) existe. &lt;br /&gt;
&lt;br /&gt;
[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&lt;br /&gt;
[[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Devuelve un valor booleano que nos dice si estamos en una XO o no. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36226</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36226"/>
		<updated>2009-08-31T16:41:45Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36225</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36225"/>
		<updated>2009-08-31T16:38:18Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.&lt;br /&gt;
Ten claro que espacio libre en el sistema de archivos realmente te importa.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36224</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36224"/>
		<updated>2009-08-31T16:38:00Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [http://docs.python.org/lib/module-statvfs.html statvfs]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en /home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Método getFreespaceKb: devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.&lt;br /&gt;
Ten claro que el espacio libre en el sistema de archivos realmente te importa importa.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36223</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36223"/>
		<updated>2009-08-31T16:36:20Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* ¿Cómo puedo obtener la cantidad de espacio libre disponible en el disco dentro el directorio /home? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible dentro del directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [statvfs http://docs.python.org/lib/module-statvfs.html]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en / home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.&lt;br /&gt;
Ten claro que el espacio libre en el sistema de archivos realmente te importa importa.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36222</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36222"/>
		<updated>2009-08-31T16:35:47Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* How do I get the amount of free space available on disk under the /home directory tree? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo obtener la cantidad de espacio libre disponible en el disco dentro el directorio /home? ===&lt;br /&gt;
La siguiente función usa el módulo [statvfs http://docs.python.org/lib/module-statvfs.html]. El código siguiente muestra cómo obtener la cantidad total de espacio libre en / home. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, devuelve el espacio disponible en kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten en cuenta que asumir cosas acerca de &amp;quot;/home&amp;quot; no es una buena idea, es mejor usar os.environ[&#039;HOME&#039;]. Rainbow pondrá los archivos actuales en otros lugares, algunos en el ramdisk, otros en la flash.&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.&lt;br /&gt;
Ten en claro que el espacio libre en el sistema de archivos realmente te importa importa.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36221</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36221"/>
		<updated>2009-08-31T16:31:04Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Miscellaneous */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Varios ==&lt;br /&gt;
&lt;br /&gt;
Las tareas que aparecen más abajo son técnicas útiles que he encontrado mientras escribía código y documentación para esta referencia. No ha sido categorizadas aún.&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo se si mi actividad está &amp;quot;activa&amp;quot; o no? ===&lt;br /&gt;
&lt;br /&gt;
Puedes configurar un evento usando la constante VISIBILITY_NOTIFY_MASK para saber cuando se cambia la visibilidad. Luego en el callback para este evento lo que debes hacer es comprar el estado del evento con las variables gtk definidas para la visibilidad de tu actividad. Puedes ver [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants la sección de Constantes de Estado de Visibilidad de GDK] gtk.gdk.Constants para más información. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36219</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36219"/>
		<updated>2009-08-31T16:21:11Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Mouse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Ratón ==&lt;br /&gt;
=== ¿Cómo puedo cambiar el cursor del ratón por el cursor de espera en mi actividad? ===&lt;br /&gt;
En la subclase de tu actividad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y para volver al que está por defecto:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo rastrear la posición del ratón? ===&lt;br /&gt;
Existen varias razones por las que te puede interesar controlar la posición del ratón, que van desde el entretenimiento ([[http://en.wikipedia.org/wiki/Xeyes]]) a lo funcional (ocultar ciertas ventanas cuando el ratón no se ha movido por un par de segundos y volver a hacer aparecer esos elementos cuando este se mueva nuevamente). Esta es una manera en la cual se puede implementar esta funcionalidad:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36217</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36217"/>
		<updated>2009-08-31T16:16:05Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Audio &amp;amp; Video */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio y Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36216</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36216"/>
		<updated>2009-08-31T16:15:45Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Text and Graphics for Sugar Activities */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Texto y gráficos para las actividades de Sugar ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== ¿Cómo puedo crear un cuadro de texto para la edición de código? ===&lt;br /&gt;
Puedes usar gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Configuramos el buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# Configuramos el tipo MIME para el buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# Establecemos el objeto para la vista, usarlo como gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para agregar texto al buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Para obtener todo el texto:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probablemente quieras poner la view(vista) en un gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
y agregar el el objeto sw en vez de la view(vista).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes encotnrar más en el código fuete de Pippyy en jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36213</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36213"/>
		<updated>2009-08-31T16:09:50Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Internationalization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internacionalización ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36212</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36212"/>
		<updated>2009-08-31T16:08:00Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Logging */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/Python Standard Logging|standard de Logging en Python]]&lt;br /&gt;
&lt;br /&gt;
== Internationalization ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36211</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36211"/>
		<updated>2009-08-31T16:06:56Z</updated>

		<summary type="html">&lt;p&gt;Fede: /* Clipboard */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notas sobre el uso del [[Development Team/Almanac/GTK&#039;s Clipboard Module|módulo Clipboard de GTK ]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notes on using [[Development Team/Almanac/Python Standard Logging|Python Standard Logging]]&lt;br /&gt;
&lt;br /&gt;
== Internationalization ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36210</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36210"/>
		<updated>2009-08-31T16:05:17Z</updated>

		<summary type="html">&lt;p&gt;Fede: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* ¿Quieres comenzar con los básico del desarrollo para Sugar? Puedes visitar el [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] de OLPC Austria (&#039;&#039;Ten en cuenta que este manual fue actualizado por última vez en mayo del 2008, las capturas de tienen el diseño pre-8.2. En términos de código en sí, las cosas deberían funcionar como están descriptas. Si encuentra algún problema por favor póngase en contacto con [[User:ChristophD|ChristophD]].&#039;&#039;)  &lt;br /&gt;
* Ver también [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
Ahora, vamos con el almanaque actual...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notes on using [[Development Team/Almanac/GTK&#039;s Clipboard Module|GTK&#039;s Clipboard Module]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notes on using [[Development Team/Almanac/Python Standard Logging|Python Standard Logging]]&lt;br /&gt;
&lt;br /&gt;
== Internationalization ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36209</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36209"/>
		<updated>2009-08-31T15:57:16Z</updated>

		<summary type="html">&lt;p&gt;Fede: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== ¿Cómo puedo obtener ayuda adicional más allá de este almanaque? ==&lt;br /&gt;
* Looking to get started with the basics of Sugar development? Check out OLPC Austria&#039;s [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] (&#039;&#039;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]].&#039;&#039;)  &lt;br /&gt;
* See also [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, on to the actual almanac ...&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde puedo ver los cambios de la API? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Comenzando ==&lt;br /&gt;
=== ¿Cómo estructuro mis archivos para que sean una actividad de válido en Sugar?  === &lt;br /&gt;
Puedes encontrar información sobre la estructura de la actividad aquí: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== ¿Cómo puedo hacer un icono para mi actividad? ===&lt;br /&gt;
La información sobre lo que debe hacer se puede encontrar aquí: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Paquete: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notes on using [[Development Team/Almanac/GTK&#039;s Clipboard Module|GTK&#039;s Clipboard Module]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notes on using [[Development Team/Almanac/Python Standard Logging|Python Standard Logging]]&lt;br /&gt;
&lt;br /&gt;
== Internationalization ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36207</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36207"/>
		<updated>2009-08-31T15:51:47Z</updated>

		<summary type="html">&lt;p&gt;Fede: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== How do I get additional help beyond this almanac? ==&lt;br /&gt;
* Looking to get started with the basics of Sugar development? Check out OLPC Austria&#039;s [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] (&#039;&#039;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]].&#039;&#039;)  &lt;br /&gt;
* See also [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, on to the actual almanac ...&lt;br /&gt;
&lt;br /&gt;
== Where can I see API changes? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
=== How do I structure my files so that they are a valid sugar activity?  === &lt;br /&gt;
Information on activity bundle structure can be found here: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== How do I make an icon for my activity? ===&lt;br /&gt;
Information on what you need to do can be found here: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notes on using [[Development Team/Almanac/GTK&#039;s Clipboard Module|GTK&#039;s Clipboard Module]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notes on using [[Development Team/Almanac/Python Standard Logging|Python Standard Logging]]&lt;br /&gt;
&lt;br /&gt;
== Internationalization ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36206</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36206"/>
		<updated>2009-08-31T15:48:43Z</updated>

		<summary type="html">&lt;p&gt;Fede: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/incomplete/{{SUBPAGENAME}}}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac&amp;diff=36203</id>
		<title>Development Team/Almanac</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac&amp;diff=36203"/>
		<updated>2009-08-31T15:45:53Z</updated>

		<summary type="html">&lt;p&gt;Fede: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Translations}}&lt;br /&gt;
{{Almanac}}&lt;br /&gt;
{{Almanac TOC}}&lt;br /&gt;
== How do I get additional help beyond this almanac? ==&lt;br /&gt;
* Looking to get started with the basics of Sugar development? Check out OLPC Austria&#039;s [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] (&#039;&#039;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]].&#039;&#039;)  &lt;br /&gt;
* See also [[Development Team/Almanac/Code Snippets]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, on to the actual almanac ...&lt;br /&gt;
&lt;br /&gt;
== Where can I see API changes? ==&lt;br /&gt;
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
=== How do I structure my files so that they are a valid sugar activity?  === &lt;br /&gt;
Information on activity bundle structure can be found here: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]&lt;br /&gt;
&lt;br /&gt;
=== How do I make an icon for my activity? ===&lt;br /&gt;
Information on what you need to do can be found here: [[Development Team/Almanac/Making Icons|Making Icons]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.env|sugar.env]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.profile|sugar.profile]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.mime|sugar.mime]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.activity ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.datastore ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.graphics ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]&lt;br /&gt;
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]&lt;br /&gt;
&lt;br /&gt;
== Package: sugar.presence ==&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]&lt;br /&gt;
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]&lt;br /&gt;
&lt;br /&gt;
== Clipboard ==&lt;br /&gt;
* Notes on using [[Development Team/Almanac/GTK&#039;s Clipboard Module|GTK&#039;s Clipboard Module]]&lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
* [[Development Team/Almanac/sugar.logger|sugar.logger]]&lt;br /&gt;
* Notes on using [[Development Team/Almanac/Python Standard Logging|Python Standard Logging]]&lt;br /&gt;
&lt;br /&gt;
== Internationalization ==&lt;br /&gt;
*[[Development Team/Almanac/Internationalization|Internationalization]]&lt;br /&gt;
&lt;br /&gt;
== Text and Graphics for Sugar Activities ==&lt;br /&gt;
* [[Development Team/Almanac/Pango|Pango]]&lt;br /&gt;
=== How do I create a text box for code editing? ===&lt;br /&gt;
You can use gtksourceview2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gtk&lt;br /&gt;
import gtksourceview2&lt;br /&gt;
from sugar.graphics import style&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# set up the buffer&lt;br /&gt;
buffer = gtksourceview2.Buffer()&lt;br /&gt;
if hasattr(buffer, &#039;set_highlight&#039;): # handle different API versions&lt;br /&gt;
    buffer.set_highlight(True)&lt;br /&gt;
else:&lt;br /&gt;
    buffer.set_highlight_syntax(True)&lt;br /&gt;
&lt;br /&gt;
# set mime type for the buffer&lt;br /&gt;
lang_manager = gtksourceview2.language_manager_get_default()&lt;br /&gt;
if hasattr(lang_manager, &#039;list_languages&#039;): # again, handle different APIs&lt;br /&gt;
    langs = lang_manager.list_languages()&lt;br /&gt;
else:&lt;br /&gt;
    lang_ids = lang_manager.get_language_ids()&lt;br /&gt;
    langs = [lang_manager.get_language(lang_id) &lt;br /&gt;
                  for lang_id in lang_ids]&lt;br /&gt;
for lang in langs:&lt;br /&gt;
    for m in lang.get_mime_types():&lt;br /&gt;
        if m == mime_type:        # &amp;lt;-- this is the mime type you want&lt;br /&gt;
            buffer.set_language(lang)&lt;br /&gt;
&lt;br /&gt;
# set up the view object, use it like gtk.TextView&lt;br /&gt;
view = gtksourceview2.View(buffer)&lt;br /&gt;
view.set_size_request(300, 450)&lt;br /&gt;
view.set_editable(True)&lt;br /&gt;
view.set_cursor_visible(True)&lt;br /&gt;
view.set_show_line_numbers(True)&lt;br /&gt;
view.set_wrap_mode(gtk.WRAP_CHAR)&lt;br /&gt;
view.set_right_margin_position(80)&lt;br /&gt;
#view.set_highlight_current_line(True) #FIXME: Ugly color&lt;br /&gt;
view.set_auto_indent(True)&lt;br /&gt;
view.modify_font(pango.FontDescription(&amp;quot;Monospace &amp;quot; +&lt;br /&gt;
                 str(style.FONT_SIZE)))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set the text in the buffer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
buffer.set_text(text)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To get all the text:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably want to put the view in a gtk.ScrolledWindow&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sw = gtk.ScrolledWindow()&lt;br /&gt;
sw.add(view)&lt;br /&gt;
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and add the sw object instead of the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find more in the Pippy source and in jarabe.view.sourceview.&lt;br /&gt;
&lt;br /&gt;
== Audio &amp;amp; Video ==&lt;br /&gt;
* [[Development Team/Almanac/GStreamer|GStreamer]]&lt;br /&gt;
&lt;br /&gt;
== Mouse ==&lt;br /&gt;
=== How do I change the mouse cursor in my activity to the wait cursor? ===&lt;br /&gt;
In your activity subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( gtk.gdk.Cursor(gtk.gdk.WATCH) )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and to switch it back to the default:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
self.window.set_cursor( None );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I track the position of the mouse? ===&lt;br /&gt;
There are many different reasons you might want to track the position of the mouse in your activity, ranging from the entertaining ([[http://en.wikipedia.org/wiki/Xeyes]]) to the functional (hiding certain windows when the mouse hasn&#039;t moved for a couple of seconds and making those ui elements re-appear when the mouse has moved again).  Here is one way you can implement this functionality:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		...&lt;br /&gt;
		self.hideWidgetsTime = time.time()&lt;br /&gt;
		self.mx = -1&lt;br /&gt;
		self.my = -1&lt;br /&gt;
		self.HIDE_WIDGET_TIMEOUT_ID = gobject.timeout_add( 500, self.mouseMightHaveMovedCb )&lt;br /&gt;
&lt;br /&gt;
	def _mouseMightHaveMovedCb( self ):&lt;br /&gt;
		x, y = self.get_pointer()&lt;br /&gt;
		passedTime = 0&lt;br /&gt;
&lt;br /&gt;
		if (x != self.mx or y != self.my):&lt;br /&gt;
			self.hideWidgetsTime = time.time()&lt;br /&gt;
			if (self.hiddenWidgets):&lt;br /&gt;
				self.showWidgets()&lt;br /&gt;
				self.hiddenWidgets = False&lt;br /&gt;
		else:&lt;br /&gt;
			passedTime = time.time() - self.hideWidgetsTime&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		if (passedTime &amp;gt;= 3):&lt;br /&gt;
			if (not self.hiddenWidgets):&lt;br /&gt;
				self.hideWidgets()&lt;br /&gt;
				self.hiddenWidgets = True&lt;br /&gt;
&lt;br /&gt;
		self.mx = x&lt;br /&gt;
		self.my = y&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
The tasks below are random useful techniques that have come up as I write code and documentation for this reference. They have yet to be categorized, but will be as a sufficient set of related entries are written.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I know when my activity is &amp;quot;active&amp;quot; or not? ===&lt;br /&gt;
&lt;br /&gt;
You can set an event using the VISIBILITY_NOTIFY_MASK constant in order to know when your activity changes visibility. Then in the callback for this event, you simply compare the event&#039;s state to gtk-defined variables for activity visibility. See the [http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-visibility-state-constants GDK Visibility State Constants] section of gtk.gdk.Constants for more information. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        # Notify when the visibility state changes by calling self.__visibility_notify_cb&lt;br /&gt;
        # (PUT THIS IN YOUR ACTIVITY CODE - EG. THE __init__() METHOD)&lt;br /&gt;
        self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)&lt;br /&gt;
        self.connect(&amp;quot;visibility-notify-event&amp;quot;, self.__visibility_notify_cb)&lt;br /&gt;
    ...&lt;br /&gt;
    # Callback method for when the activity&#039;s visibility changes&lt;br /&gt;
    def __visibility_notify_cb(self, window, event):&lt;br /&gt;
        if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:&lt;br /&gt;
            print &amp;quot;I am not visible&amp;quot;&lt;br /&gt;
        elif event.state in [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]:&lt;br /&gt;
            print &amp;quot;I am visible&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I get the amount of free space available on disk under the /home directory tree? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Method: getFreespaceKb, returns the available freespace in kilobytes. &lt;br /&gt;
    def getFreespaceKb(self):&lt;br /&gt;
        stat = os.statvfs(&amp;quot;/home&amp;quot;)&lt;br /&gt;
        freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]&lt;br /&gt;
        freekb = freebytes / 1024&lt;br /&gt;
        return freekb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, however, that assuming anything about &amp;quot;/home&amp;quot; is a bad idea, better use os.environ[&#039;HOME&#039;] instead.  Rainbow will put your actual files elsewhere,&lt;br /&gt;
some on ramdisks, some on flash.  Be clear about which filesystem&#039;s free space you actually care about.&lt;br /&gt;
&lt;br /&gt;
=== How do I know whether my activity is running on a physical XO? ===&lt;br /&gt;
Sugar runs on ordinary computers as well as on XO&#039;s.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn&#039;t write your activity to care whether it&#039;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. &amp;lt;ref&amp;gt;[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;OLPC [[olpc:Power Management Interface]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
      #Print out a boolean value that tells us whether we are on an XO or not. &lt;br /&gt;
      print os.path.exists(&#039;/sys/power/olpc-pm&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I know the current language setting on my XO? ===&lt;br /&gt;
The system variable &#039;LANG&#039; tells you which language is currently active on the XO. The following code shows how to look at the value of this variable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
...&lt;br /&gt;
       _logger.debug(os.environ[&#039;LANG&#039;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I repeatedly call a specific method after N number of seconds? ===&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	#This method calls itself ROUGHLY every 1 second &lt;br /&gt;
	def repeatedly_call(self):&lt;br /&gt;
		now = datetime.datetime.now()&lt;br /&gt;
		gobject.timeout_add(self.repeat_period_msec, self.repeatedly_update_time)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I update the current build version of code that is running on my XO? ===&lt;br /&gt;
&lt;br /&gt;
There are several pages that give you instructions on how to install/update your current build. &lt;br /&gt;
&lt;br /&gt;
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]]. &lt;br /&gt;
* If that doesn&#039;t work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot. &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===&lt;br /&gt;
&lt;br /&gt;
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]]&lt;br /&gt;
&lt;br /&gt;
Keyboard settings on internationalized laptops&amp;lt;ref&amp;gt;[[olpc:Keyboard layouts#OLPC keyboard layouts]]&amp;lt;/ref&amp;gt; can also be suboptimal, especially as characters like &amp;quot;-&amp;quot; and &amp;quot;/&amp;quot; are in unfamiliar positions. You can use the &amp;lt;tt&amp;gt;setxkbmap&amp;lt;/tt&amp;gt; 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). &lt;br /&gt;
&lt;br /&gt;
 setxkbmap us&lt;br /&gt;
&lt;br /&gt;
=== My Python activity wants to use threads; how do I do that? ===&lt;br /&gt;
&lt;br /&gt;
A question that has been answered with limited success is which threading patterns are most appropriate for use in Sugar.  The following pattern of code to work fine in basic instances:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #### Method: __init__, initialize this AnnotateActivity instance&lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.sample_thread = Thread(target=self.announce_thread, args=())&lt;br /&gt;
        self.sample_thread.setDaemon(0)&lt;br /&gt;
        self.sample_thread.start()&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    def announce_thread(self):&lt;br /&gt;
        while (self.Running):&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
            print &amp;quot;thread running&amp;quot;&lt;br /&gt;
            self._update_chat_text(&amp;quot;Thread&amp;quot;, &amp;quot;In here&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the basic series of steps that most online documentation on python suggests to use when trying to work with threads in python. The problem is that it is unclear how this pattern relates to code that worked in the SimCity activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import gobject&lt;br /&gt;
gobject.threads_init()&lt;br /&gt;
#import dbus.mainloop.glib&lt;br /&gt;
#dbus.mainloop.glib.threads_init()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that in the SimCity activity the pygame sound player would not produce sound reliably unless this setup was done.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should the two patterns always be used in tandem? It seems that the latter code is mainly to initiate gobject and other libraries to work with threading, but it is unclear what restrictions there are with using threading with these libraries. Does one take precedence over the other? It is not clear if there is any problem with using the standard python threading code on the sugar technology stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, experiments with threading on sugar leads to several different problems. For one thing, thread termination was tricky - using the can_close() method for sugar activities to terminate an activity only killed threads in some circumstances. It did not properly handle terminating threads in the case of CTRL-C or terminal interrupts. You can try to catch signals (SIGINT, SIGTERM or SIGHUP), but you will still be running in to errors in terminating child threads using these as well. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I customize the title that is displayed for each instance of my activity? ===&lt;br /&gt;
&lt;br /&gt;
By default, activity titles are just the generic activity names that you specify in your activity.info file. In some applications, you may want the activity title to be more dynamic. &lt;br /&gt;
&lt;br /&gt;
For example, it makes sense to set the title for different browser sessions to the active web page being visited. That way, when you look back in the journal at the different browser sessions you have run in the previous few days, you can identify unique sessions based on the website you happened to be visiting at the time. &lt;br /&gt;
&lt;br /&gt;
The code below shows how you can set the metadata for your activity to reflect a dynamic title based on whatever session criteria you feel is important. This example is adapted from the Browse activity, which sets activity instance titles based on the title of the current web page being visited. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        if self.metadata[&#039;mime_type&#039;] == &#039;text/plain&#039;:&lt;br /&gt;
            if not self._jobject.metadata[&#039;title_set_by_user&#039;] == &#039;1&#039;:&lt;br /&gt;
                if self._browser.props.title:&lt;br /&gt;
                    # Set the title of this activity to be the current &lt;br /&gt;
                    # title of the page being visited by the browser. &lt;br /&gt;
                    self.metadata[&#039;title&#039;] = self._browser.props.title&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What packages are available on sugar to support game development? ===&lt;br /&gt;
&lt;br /&gt;
If your activity will require tools that are typically needed to develop robust and clean video games, then you should utilize the [http://www.pygame.org/ pygame package]. It can be readily imported into any activity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import pygame&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I detect when one of the game buttons on the laptop have been pressed? ===&lt;br /&gt;
&lt;br /&gt;
The laptop game buttons (the circle, square, x, and check buttons next to the LCD) are encoded as page up, home, page down and end respectively. So, you can detect their press by listening for these specific events. For example, the code below listens for button presses and then just writes to an output widget which button was pressed. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Page_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCircle Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Page_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nX Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Home&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nSquare Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_End&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nCheck Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How do I detect if one of the joystick buttons has been pressed? ===&lt;br /&gt;
&lt;br /&gt;
This is the same process as detecting game buttons, except with different names for the keys. Again, you listen for &amp;quot;key-press-event&amp;quot; signals and then in your callback you check to see if the pressed button was one of the joystick keys. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    #### Initialize this activity. &lt;br /&gt;
    def __init__(self, handle):&lt;br /&gt;
        ...&lt;br /&gt;
        self.connect(&#039;key-press-event&#039;, self._keyPressCb)&lt;br /&gt;
        ...&lt;br /&gt;
&lt;br /&gt;
    #### Method _keyPressCb, which catches any presses of the game buttons. &lt;br /&gt;
    def _keyPressCb(self, widget, event):&lt;br /&gt;
&lt;br /&gt;
        keyname = gtk.gdk.keyval_name(event.keyval)&lt;br /&gt;
        &lt;br /&gt;
        if (keyname == &#039;KP_Up&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nUp Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Down&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nDown Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Left&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nLeft Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
        elif (keyname == &#039;KP_Right&#039;):&lt;br /&gt;
            self._chat += &amp;quot;\nRight Pressed!&amp;quot;&lt;br /&gt;
            self._chat_buffer.set_text(self._chat)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do i remove an specific button from the toolbar? ===&lt;br /&gt;
&lt;br /&gt;
This is an example of the share button is removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    activity_toolbar = toolbox.get_activity_toolbar()&lt;br /&gt;
    activity_toolbar.remove(activity_toolbar.share)&lt;br /&gt;
    activity_toolbar.share = None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Development Team]]&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/translations&amp;diff=36202</id>
		<title>Development Team/Almanac/translations</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/translations&amp;diff=36202"/>
		<updated>2009-08-31T15:45:46Z</updated>

		<summary type="html">&lt;p&gt;Fede: Created page with &amp;#039;{{Translationlist | es | origlang=en | translated={{{translated}}}}}&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Translationlist | es | origlang=en | translated={{{translated}}}}}&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36201</id>
		<title>Development Team/Almanac/lang-es</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Almanac/lang-es&amp;diff=36201"/>
		<updated>2009-08-31T15:45:43Z</updated>

		<summary type="html">&lt;p&gt;Fede: Created page with &amp;#039;{{subst:requesttranslation}}&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{translation&lt;br /&gt;
  | source = Development_Team/Almanac&lt;br /&gt;
  | lang = es&lt;br /&gt;
  | status = {{translation/wanted/{{SUBPAGENAME}}}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Fede</name></author>
	</entry>
</feed>