[Sugar-devel] [PATCH] Sort the activities in the home in alphabetic order

2012-10-04 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The change is done in the favorites view and in the list view

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/activitieslist.py  | 1 +
 src/jarabe/desktop/favoriteslayout.py | 6 +-
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/jarabe/desktop/activitieslist.py 
b/src/jarabe/desktop/activitieslist.py
index 1b5ddd7..3b07e87 100644
--- a/src/jarabe/desktop/activitieslist.py
+++ b/src/jarabe/desktop/activitieslist.py
@@ -179,6 +179,7 @@ class ListModel(Gtk.TreeModelSort):
 self._model = Gtk.ListStore(str, bool, str, str, str, str, int, str)
 self._model_filter = self._model.filter_new()
 Gtk.TreeModelSort.__init__(self, model=self._model_filter)
+self.set_sort_column_id(ListModel.COLUMN_TITLE, Gtk.SortType.ASCENDING)
 
 GObject.idle_add(self.__connect_to_bundle_registry_cb)
 
diff --git a/src/jarabe/desktop/favoriteslayout.py 
b/src/jarabe/desktop/favoriteslayout.py
index a367ab6..eb5deef 100644
--- a/src/jarabe/desktop/favoriteslayout.py
+++ b/src/jarabe/desktop/favoriteslayout.py
@@ -387,11 +387,7 @@ class RingLayout(ViewLayout):
 child.size_allocate(child_allocation)
 
 def compare_activities(self, icon_a, icon_b):
-if hasattr(icon_a, 'installation_time') and \
-hasattr(icon_b, 'installation_time'):
-return int(icon_b.installation_time - icon_a.installation_time)
-else:
-return 0
+return cmp(icon_a.get_activity_name(), icon_b.get_activity_name())
 
 
 _SUNFLOWER_CONSTANT = style.STANDARD_ICON_SIZE * .75
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk2] Add management of summary property to the activity.info file - v2

2012-09-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This summary is translatable aas the name and will be displayed
in the activivity list in the home view.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

v2: remove installation_time because is not used anymore
---
 src/sugar3/activity/bundlebuilder.py |  9 +
 src/sugar3/bundle/activitybundle.py  | 21 +++--
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/sugar3/activity/bundlebuilder.py 
b/src/sugar3/activity/bundlebuilder.py
index 0e4af59..1450ec2 100644
--- a/src/sugar3/activity/bundlebuilder.py
+++ b/src/sugar3/activity/bundlebuilder.py
@@ -77,6 +77,7 @@ class Config(object):
 self.tar_root_dir = None
 self.xo_name = None
 self.tar_name = None
+self.summary = None
 
 self.update()
 
@@ -85,6 +86,7 @@ class Config(object):
 self.version = bundle.get_activity_version()
 self.activity_name = bundle.get_bundle_name()
 self.bundle_id = bundle.get_bundle_id()
+self.summary = bundle.get_summary()
 self.bundle_name = reduce(operator.add, self.activity_name.split())
 self.bundle_root_dir = self.bundle_name + '.activity'
 self.tar_root_dir = '%s-%s' % (self.bundle_name, self.version)
@@ -136,9 +138,11 @@ class Builder(object):
 
 cat = gettext.GNUTranslations(open(mo_file, 'r'))
 translated_name = cat.gettext(self.config.activity_name)
+translated_summary = cat.gettext(self.config.summary)
 linfo_file = os.path.join(localedir, 'activity.linfo')
 f = open(linfo_file, 'w')
 f.write('[Activity]\nname = %s\n' % translated_name)
+f.write('summary = %s\n' % translated_summary)
 f.close()
 
 def get_files(self):
@@ -356,6 +360,11 @@ def cmd_genpot(config, args):
 f.write('#: activity/activity.info:2\n')
 f.write('msgid %s\n' % escaped_name)
 f.write('msgstr \n')
+if config.summary is not None:
+escaped_summary = re.sub('([])', '\\1', config.summary)
+f.write('#: activity/activity.info:3\n')
+f.write('msgid %s\n' % escaped_summary)
+f.write('msgstr \n')
 f.close()
 
 args = ['xgettext', '--join-existing', '--language=Python',
diff --git a/src/sugar3/bundle/activitybundle.py 
b/src/sugar3/bundle/activitybundle.py
index 2313f41..f686715 100644
--- a/src/sugar3/bundle/activitybundle.py
+++ b/src/sugar3/bundle/activitybundle.py
@@ -61,7 +61,8 @@ class ActivityBundle(Bundle):
 self._show_launcher = True
 self._tags = None
 self._activity_version = '0'
-self._installation_time = os.stat(path).st_mtime
+self._summary = None
+self._local_summary = None
 
 info_file = self.get_file('activity/activity.info')
 if info_file is None:
@@ -75,6 +76,9 @@ class ActivityBundle(Bundle):
 if self._local_name == None:
 self._local_name = self._name
 
+if self._local_summary == None:
+self._local_summary = self._summary
+
 def _parse_info(self, info_file):
 cp = ConfigParser()
 cp.readfp(info_file)
@@ -126,6 +130,9 @@ class ActivityBundle(Bundle):
 (self._path, version))
 self._activity_version = version
 
+if cp.has_option(section, 'summary'):
+self._summary = cp.get(section, 'summary')
+
 def _get_linfo_file(self):
 lang = locale.getdefaultlocale()[0]
 if not lang:
@@ -152,6 +159,9 @@ class ActivityBundle(Bundle):
 if cp.has_option(section, 'name'):
 self._local_name = cp.get(section, 'name')
 
+if cp.has_option(section, 'summary'):
+self._local_summary = cp.get(section, 'summary')
+
 if cp.has_option(section, 'tags'):
 tag_list = cp.get(section, 'tags').strip(';')
 self._tags = [tag.strip() for tag in tag_list.split(';')]
@@ -180,11 +190,6 @@ class ActivityBundle(Bundle):
 Get the activity bundle name.
 return self._name
 
-def get_installation_time(self):
-Get a timestamp representing the time at which this activity was
-installed.
-return self._installation_time
-
 def get_bundle_id(self):
 Get the activity bundle id
 return self._bundle_id
@@ -225,6 +230,10 @@ class ActivityBundle(Bundle):
 Get the tags that describe the activity
 return self._tags
 
+def get_summary(self):
+Get the summary that describe the activity
+return self._local_summary
+
 def get_show_launcher(self):
 Get whether there should be a visible launcher for the activity
 return self._show_launcher
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar] Show summary information in the activities list view - v2

2012-09-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The listview and the favoritesview are sorted by the localized activity name
instead of installation time. The installation time is not used anymore
and was removed. The search is done now in the title and in the summary fields.
The version column is moved at the right.

A pending issue is the space between columns, probably should be set in the 
theme.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/activitieslist.py  | 36 +--
 src/jarabe/desktop/favoriteslayout.py |  9 +
 src/jarabe/desktop/favoritesview.py   |  4 
 3 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/src/jarabe/desktop/activitieslist.py 
b/src/jarabe/desktop/activitieslist.py
index b64..1dd4e75 100644
--- a/src/jarabe/desktop/activitieslist.py
+++ b/src/jarabe/desktop/activitieslist.py
@@ -26,7 +26,6 @@ from gi.repository import GConf
 from gi.repository import Gtk
 from gi.repository import Gdk
 
-from sugar3 import util
 from sugar3.graphics import style
 from sugar3.graphics.icon import Icon, CellRendererIcon
 from sugar3.graphics.xocolor import XoColor
@@ -79,29 +78,28 @@ class ActivitiesTreeView(Gtk.TreeView):
 self.append_column(column)
 
 cell_text = Gtk.CellRendererText()
-cell_text.props.ellipsize = Pango.EllipsizeMode.MIDDLE
-cell_text.props.ellipsize_set = True
 
 column = Gtk.TreeViewColumn()
 column.props.sizing = Gtk.TreeViewColumnSizing.GROW_ONLY
-column.props.expand = True
 column.set_sort_column_id(ListModel.COLUMN_TITLE)
 column.pack_start(cell_text, True)
 column.add_attribute(cell_text, 'markup', ListModel.COLUMN_TITLE)
 self.append_column(column)
 
 cell_text = Gtk.CellRendererText()
-cell_text.props.xalign = 1
+cell_text.props.xalign = 0
+cell_text.props.wrap_width = int(Gdk.Screen.width() / 3)
+cell_text.props.wrap_mode = Pango.WrapMode.WORD
 
 column = Gtk.TreeViewColumn()
-column.set_alignment(1)
 column.props.sizing = Gtk.TreeViewColumnSizing.GROW_ONLY
 column.props.resizable = True
 column.props.reorderable = True
 column.props.expand = True
-column.set_sort_column_id(ListModel.COLUMN_VERSION)
+column.props.max_width = int(Gdk.Screen.width() / 3)
+column.set_sort_column_id(ListModel.COLUMN_SUMMARY)
 column.pack_start(cell_text, True)
-column.add_attribute(cell_text, 'text', ListModel.COLUMN_VERSION_TEXT)
+column.add_attribute(cell_text, 'text', ListModel.COLUMN_SUMMARY)
 self.append_column(column)
 
 cell_text = Gtk.CellRendererText()
@@ -112,10 +110,9 @@ class ActivitiesTreeView(Gtk.TreeView):
 column.props.sizing = Gtk.TreeViewColumnSizing.GROW_ONLY
 column.props.resizable = True
 column.props.reorderable = True
-column.props.expand = True
-column.set_sort_column_id(ListModel.COLUMN_DATE)
+column.set_sort_column_id(ListModel.COLUMN_VERSION)
 column.pack_start(cell_text, True)
-column.add_attribute(cell_text, 'text', ListModel.COLUMN_DATE_TEXT)
+column.add_attribute(cell_text, 'text', ListModel.COLUMN_VERSION_TEXT)
 self.append_column(column)
 
 self.set_search_column(ListModel.COLUMN_TITLE)
@@ -160,7 +157,10 @@ class ActivitiesTreeView(Gtk.TreeView):
 
 def __model_visible_cb(self, model, tree_iter, data):
 title = model[tree_iter][ListModel.COLUMN_TITLE]
-return title is not None and title.lower().find(self._query)  -1
+summary = model[tree_iter][ListModel.COLUMN_SUMMARY]
+return title is not None and title.lower().find(self._query)  -1 \
+or summary is not None and \
+summary.lower().find(self._query)  -1
 
 
 class ListModel(Gtk.TreeModelSort):
@@ -172,13 +172,13 @@ class ListModel(Gtk.TreeModelSort):
 COLUMN_TITLE = 3
 COLUMN_VERSION = 4
 COLUMN_VERSION_TEXT = 5
-COLUMN_DATE = 6
-COLUMN_DATE_TEXT = 7
+COLUMN_SUMMARY = 6
 
 def __init__(self):
-self._model = Gtk.ListStore(str, bool, str, str, str, str, int, str)
+self._model = Gtk.ListStore(str, bool, str, str, str, str, str)
 self._model_filter = self._model.filter_new()
 Gtk.TreeModelSort.__init__(self, model=self._model_filter)
+self.set_sort_column_id(ListModel.COLUMN_TITLE, Gtk.SortType.ASCENDING)
 
 GObject.idle_add(self.__connect_to_bundle_registry_cb)
 
@@ -216,7 +216,6 @@ class ListModel(Gtk.TreeModelSort):
 if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
 return
 
-timestamp = activity_info.get_installation_time()
 version = activity_info.get_activity_version()
 
 registry = bundleregistry.get_registry()
@@ -232,14 +231,15 @@ class ListModel(Gtk.TreeModelSort):
 'span 

[Sugar-devel] [PATCH] Fix radiopalette due to api change in toolbotton

2012-09-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/graphics/radiopalette.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/sugar3/graphics/radiopalette.py 
b/src/sugar3/graphics/radiopalette.py
index c2ff4f6..29f4159 100644
--- a/src/sugar3/graphics/radiopalette.py
+++ b/src/sugar3/graphics/radiopalette.py
@@ -100,5 +100,5 @@ class RadioPalette(Palette):
 return
 
 parent.props.label = button.palette_label
-parent.set_icon(button.props.icon_name)
+parent.set_icon_name(button.props.icon_name)
 parent.selected_button = button
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk3] Add management of summary property to the activity.info file

2012-09-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This summary is translatable aas the name and will be displayed
in the activivity list in the home view.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/activity/bundlebuilder.py |  9 +
 src/sugar3/bundle/activitybundle.py  | 15 +++
 2 files changed, 24 insertions(+)

diff --git a/src/sugar3/activity/bundlebuilder.py 
b/src/sugar3/activity/bundlebuilder.py
index bcc7aa9..bebecfe 100644
--- a/src/sugar3/activity/bundlebuilder.py
+++ b/src/sugar3/activity/bundlebuilder.py
@@ -77,6 +77,7 @@ class Config(object):
 self.tar_root_dir = None
 self.xo_name = None
 self.tar_name = None
+self.summary = None
 
 self.update()
 
@@ -85,6 +86,7 @@ class Config(object):
 self.version = bundle.get_activity_version()
 self.activity_name = bundle.get_bundle_name()
 self.bundle_id = bundle.get_bundle_id()
+self.summary = bundle.get_summary()
 self.bundle_name = reduce(operator.add, self.activity_name.split())
 self.bundle_root_dir = self.bundle_name + '.activity'
 self.tar_root_dir = '%s-%s' % (self.bundle_name, self.version)
@@ -136,9 +138,11 @@ class Builder(object):
 
 cat = gettext.GNUTranslations(open(mo_file, 'r'))
 translated_name = cat.gettext(self.config.activity_name)
+translated_summary = cat.gettext(self.config.summary)
 linfo_file = os.path.join(localedir, 'activity.linfo')
 f = open(linfo_file, 'w')
 f.write('[Activity]\nname = %s\n' % translated_name)
+f.write('summary = %s\n' % translated_summary)
 f.close()
 
 def get_files(self):
@@ -346,6 +350,11 @@ def cmd_genpot(config, args):
 f.write('#: activity/activity.info:2\n')
 f.write('msgid %s\n' % escaped_name)
 f.write('msgstr \n')
+if config.summary is not None:
+escaped_summary = re.sub('([])', '\\1', config.summary)
+f.write('#: activity/activity.info:3\n')
+f.write('msgid %s\n' % escaped_summary)
+f.write('msgstr \n')
 f.close()
 
 args = ['xgettext', '--join-existing', '--language=Python',
diff --git a/src/sugar3/bundle/activitybundle.py 
b/src/sugar3/bundle/activitybundle.py
index 2313f41..f7933ef 100644
--- a/src/sugar3/bundle/activitybundle.py
+++ b/src/sugar3/bundle/activitybundle.py
@@ -61,6 +61,8 @@ class ActivityBundle(Bundle):
 self._show_launcher = True
 self._tags = None
 self._activity_version = '0'
+self._summary = None
+self._local_summary = None
 self._installation_time = os.stat(path).st_mtime
 
 info_file = self.get_file('activity/activity.info')
@@ -75,6 +77,9 @@ class ActivityBundle(Bundle):
 if self._local_name == None:
 self._local_name = self._name
 
+if self._local_summary == None:
+self._local_summary = self._summary
+
 def _parse_info(self, info_file):
 cp = ConfigParser()
 cp.readfp(info_file)
@@ -126,6 +131,9 @@ class ActivityBundle(Bundle):
 (self._path, version))
 self._activity_version = version
 
+if cp.has_option(section, 'summary'):
+self._summary = cp.get(section, 'summary')
+
 def _get_linfo_file(self):
 lang = locale.getdefaultlocale()[0]
 if not lang:
@@ -152,6 +160,9 @@ class ActivityBundle(Bundle):
 if cp.has_option(section, 'name'):
 self._local_name = cp.get(section, 'name')
 
+if cp.has_option(section, 'summary'):
+self._local_summary = cp.get(section, 'summary')
+
 if cp.has_option(section, 'tags'):
 tag_list = cp.get(section, 'tags').strip(';')
 self._tags = [tag.strip() for tag in tag_list.split(';')]
@@ -225,6 +236,10 @@ class ActivityBundle(Bundle):
 Get the tags that describe the activity
 return self._tags
 
+def get_summary(self):
+Get the summary that describe the activity
+return self._local_summary
+
 def get_show_launcher(self):
 Get whether there should be a visible launcher for the activity
 return self._show_launcher
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk3] Make icon_name api consistent between the different toolbuttons

2012-09-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

As discused in the mailing list [1] the api to set the icon in sugar
ToolButton, RadioToolButton and ToggleToolButton is inconsistent,
and with the port to gtk3 differences are visible as a wrong size (SL #3849)

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

[1] http://lists.sugarlabs.org/archive/sugar-devel/2012-September/039624.html
---
 src/sugar3/graphics/radiotoolbutton.py  | 20 +++-
 src/sugar3/graphics/toggletoolbutton.py | 11 +++
 2 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/src/sugar3/graphics/radiotoolbutton.py 
b/src/sugar3/graphics/radiotoolbutton.py
index 006d167..290e7c2 100644
--- a/src/sugar3/graphics/radiotoolbutton.py
+++ b/src/sugar3/graphics/radiotoolbutton.py
@@ -36,7 +36,7 @@ class RadioToolButton(Gtk.RadioToolButton):
 
 __gtype_name__ = 'SugarRadioToolButton'
 
-def __init__(self, **kwargs):
+def __init__(self, icon_name=None, **kwargs):
 self._accelerator = None
 self._tooltip = None
 self._xo_color = None
@@ -45,6 +45,8 @@ class RadioToolButton(Gtk.RadioToolButton):
 GObject.GObject.__init__(self, **kwargs)
 
 self._palette_invoker.attach_tool(self)
+if icon_name:
+self.set_icon(icon_name)
 
 self.connect('destroy', self.__destroy_cb)
 
@@ -115,21 +117,13 @@ class RadioToolButton(Gtk.RadioToolButton):
 accelerator = GObject.property(type=str, setter=set_accelerator,
 getter=get_accelerator)
 
-def set_named_icon(self, named_icon):
-icon = Icon(icon_name=named_icon,
-xo_color=self._xo_color,
-icon_size=Gtk.IconSize.LARGE_TOOLBAR)
+def set_icon(self, icon_name):
+icon = Icon(icon_name=icon_name,
+xo_color=self._xo_color)
 self.set_icon_widget(icon)
 icon.show()
 
-def get_named_icon(self):
-if self.props.icon_widget is not None:
-return self.props.icon_widget.props.icon_name
-else:
-return None
-
-named_icon = GObject.property(type=str, setter=set_named_icon,
-  getter=get_named_icon)
+icon_name = GObject.property(type=str, setter=set_icon)
 
 def set_xo_color(self, xo_color):
 if self._xo_color != xo_color:
diff --git a/src/sugar3/graphics/toggletoolbutton.py 
b/src/sugar3/graphics/toggletoolbutton.py
index 56d461d..39ba0c8 100644
--- a/src/sugar3/graphics/toggletoolbutton.py
+++ b/src/sugar3/graphics/toggletoolbutton.py
@@ -30,11 +30,12 @@ class ToggleToolButton(Gtk.ToggleToolButton):
 
 __gtype_name__ = 'SugarToggleToolButton'
 
-def __init__(self, named_icon=None):
+def __init__(self, icon_name=None):
 GObject.GObject.__init__(self)
 
 self._palette_invoker = ToolInvoker(self)
-self.set_named_icon(named_icon)
+if icon_name:
+self.set_icon(icon_name)
 
 self.connect('destroy', self.__destroy_cb)
 
@@ -42,11 +43,13 @@ class ToggleToolButton(Gtk.ToggleToolButton):
 if self._palette_invoker is not None:
 self._palette_invoker.detach()
 
-def set_named_icon(self, named_icon):
-icon = Icon(icon_name=named_icon)
+def set_icon(self, icon_name):
+icon = Icon(icon_name=icon_name)
 self.set_icon_widget(icon)
 icon.show()
 
+icon_name = GObject.property(type=str, setter=set_icon)
+
 def create_palette(self):
 return None
 
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar] Replace named_icon by icon_name in ToolButton and similar

2012-09-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This change is needed by the change done in sigar-toolkit-gtk3

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/homebox.py| 4 ++--
 src/jarabe/frame/zoomtoolbar.py  | 2 +-
 src/jarabe/journal/volumestoolbar.py | 6 +++---
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/jarabe/desktop/homebox.py b/src/jarabe/desktop/homebox.py
index 59550e9..1d84c2d 100644
--- a/src/jarabe/desktop/homebox.py
+++ b/src/jarabe/desktop/homebox.py
@@ -192,7 +192,7 @@ class HomeToolbar(Gtk.Toolbar):
 self.insert(favorites_button, -1)
 favorites_button.show()
 
-self._list_button = RadioToolButton(named_icon='view-list')
+self._list_button = RadioToolButton(icon_name='view-list')
 self._list_button.props.group = favorites_button
 self._list_button.props.tooltip = _('List view')
 self._list_button.props.accelerator = _('Ctrl2')
@@ -291,5 +291,5 @@ class FavoritesButton(RadioToolButton):
 self.emit('toggled')
 
 def _update_icon(self):
-self.props.named_icon = favoritesview.LAYOUT_MAP[self._layout]\
+self.props.icon_name = favoritesview.LAYOUT_MAP[self._layout]\
 .icon_name
diff --git a/src/jarabe/frame/zoomtoolbar.py b/src/jarabe/frame/zoomtoolbar.py
index ae7d050..fcef08b 100644
--- a/src/jarabe/frame/zoomtoolbar.py
+++ b/src/jarabe/frame/zoomtoolbar.py
@@ -59,7 +59,7 @@ class ZoomToolbar(Gtk.Toolbar):
 else:
 group = None
 
-button = RadioToolButton(named_icon=icon_name, group=group,
+button = RadioToolButton(icon_name=icon_name, group=group,
  accelerator=accelerator)
 button.connect('clicked', self.__level_clicked_cb, zoom_level)
 self.add(button)
diff --git a/src/jarabe/journal/volumestoolbar.py 
b/src/jarabe/journal/volumestoolbar.py
index 0f7bdce..9c25ff6 100644
--- a/src/jarabe/journal/volumestoolbar.py
+++ b/src/jarabe/journal/volumestoolbar.py
@@ -334,7 +334,7 @@ class VolumeButton(BaseButton):
 if icon_name is None:
 icon_name = 'drive'
 
-self.props.named_icon = icon_name
+self.props.icon_name = icon_name
 
 # TODO: retrieve the colors from the owner of the device
 client = GConf.Client.get_default()
@@ -352,7 +352,7 @@ class JournalButton(BaseButton):
 def __init__(self):
 BaseButton.__init__(self, mount_point='/')
 
-self.props.named_icon = 'activity-journal'
+self.props.icon_name = 'activity-journal'
 
 client = GConf.Client.get_default()
 color = XoColor(client.get_string('/desktop/sugar/user/color'))
@@ -398,7 +398,7 @@ class DocumentsButton(BaseButton):
 def __init__(self, documents_path):
 BaseButton.__init__(self, mount_point=documents_path)
 
-self.props.named_icon = 'user-documents'
+self.props.icon_name = 'user-documents'
 
 client = GConf.Client.get_default()
 color = XoColor(client.get_string('/desktop/sugar/user/color'))
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar] Show summary information in the activities list view

2012-09-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/activitieslist.py | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/src/jarabe/desktop/activitieslist.py 
b/src/jarabe/desktop/activitieslist.py
index fc05594..58e285c 100644
--- a/src/jarabe/desktop/activitieslist.py
+++ b/src/jarabe/desktop/activitieslist.py
@@ -25,7 +25,6 @@ from gi.repository import GConf
 from gi.repository import Gtk
 from gi.repository import Gdk
 
-from sugar3 import util
 from sugar3.graphics import style
 from sugar3.graphics.icon import Icon, CellRendererIcon
 from sugar3.graphics.xocolor import XoColor
@@ -77,12 +76,9 @@ class ActivitiesTreeView(Gtk.TreeView):
 self.append_column(column)
 
 cell_text = Gtk.CellRendererText()
-cell_text.props.ellipsize = Pango.EllipsizeMode.MIDDLE
-cell_text.props.ellipsize_set = True
 
 column = Gtk.TreeViewColumn()
 column.props.sizing = Gtk.TreeViewColumnSizing.GROW_ONLY
-column.props.expand = True
 column.set_sort_column_id(ListModel.COLUMN_TITLE)
 column.pack_start(cell_text, True)
 column.add_attribute(cell_text, 'markup', ListModel.COLUMN_TITLE)
@@ -96,24 +92,26 @@ class ActivitiesTreeView(Gtk.TreeView):
 column.props.sizing = Gtk.TreeViewColumnSizing.GROW_ONLY
 column.props.resizable = True
 column.props.reorderable = True
-column.props.expand = True
 column.set_sort_column_id(ListModel.COLUMN_VERSION)
 column.pack_start(cell_text, True)
 column.add_attribute(cell_text, 'text', ListModel.COLUMN_VERSION_TEXT)
 self.append_column(column)
 
 cell_text = Gtk.CellRendererText()
-cell_text.props.xalign = 1
+cell_text.props.xalign = 0
+cell_text.props.wrap_width = int(Gdk.Screen.width() / 3)
+cell_text.props.wrap_mode = Pango.WrapMode.WORD
 
 column = Gtk.TreeViewColumn()
-column.set_alignment(1)
 column.props.sizing = Gtk.TreeViewColumnSizing.GROW_ONLY
 column.props.resizable = True
 column.props.reorderable = True
 column.props.expand = True
-column.set_sort_column_id(ListModel.COLUMN_DATE)
+column.props.max_width = int(Gdk.Screen.width() / 3)
+column.props.spacing = 5
+column.set_sort_column_id(ListModel.COLUMN_SUMMARY)
 column.pack_start(cell_text, True)
-column.add_attribute(cell_text, 'text', ListModel.COLUMN_DATE_TEXT)
+column.add_attribute(cell_text, 'text', ListModel.COLUMN_SUMMARY)
 self.append_column(column)
 
 self.set_search_column(ListModel.COLUMN_TITLE)
@@ -164,11 +162,10 @@ class ListModel(Gtk.TreeModelSort):
 COLUMN_TITLE = 3
 COLUMN_VERSION = 4
 COLUMN_VERSION_TEXT = 5
-COLUMN_DATE = 6
-COLUMN_DATE_TEXT = 7
+COLUMN_SUMMARY = 6
 
 def __init__(self):
-self._model = Gtk.ListStore(str, bool, str, str, str, str, int, str)
+self._model = Gtk.ListStore(str, bool, str, str, str, str, str)
 self._model_filter = self._model.filter_new()
 Gtk.TreeModelSort.__init__(self, model=self._model_filter)
 
@@ -208,7 +205,6 @@ class ListModel(Gtk.TreeModelSort):
 if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
 return
 
-timestamp = activity_info.get_installation_time()
 version = activity_info.get_activity_version()
 
 registry = bundleregistry.get_registry()
@@ -224,14 +220,15 @@ class ListModel(Gtk.TreeModelSort):
 'span style=italic weight=light%s/span' % \
 (activity_info.get_name(), tags)
 
+summary = activity_info.get_summary()
+
 self._model.append([activity_info.get_bundle_id(),
 favorite,
 activity_info.get_icon(),
 title,
 version,
 _('Version %s') % version,
-int(timestamp),
-util.timestamp_to_elapsed_string(timestamp)])
+summary])
 
 def set_visible_func(self, func):
 self._model_filter.set_visible_func(func)
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk3] Set getter an setter in icon_name property - SL #3849

2012-09-18 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

With g-i bindings, setting the property don't change the size
and the button is bigger than should be.
Now we have two properties for the same, icon_name and named_icon,
maybe one should be deprecated.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/graphics/radiotoolbutton.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/sugar3/graphics/radiotoolbutton.py 
b/src/sugar3/graphics/radiotoolbutton.py
index 006d167..0c44347 100644
--- a/src/sugar3/graphics/radiotoolbutton.py
+++ b/src/sugar3/graphics/radiotoolbutton.py
@@ -131,6 +131,9 @@ class RadioToolButton(Gtk.RadioToolButton):
 named_icon = GObject.property(type=str, setter=set_named_icon,
   getter=get_named_icon)
 
+icon_name = GObject.property(type=str, setter=set_named_icon,
+  getter=get_named_icon)
+
 def set_xo_color(self, xo_color):
 if self._xo_color != xo_color:
 self._xo_color = xo_color
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Take list of supported image formats mime types from GdkPixbuf - SL #3845

2012-09-03 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
Acked-by: Simon Schampijer si...@laptop.org
---
 src/sugar3/mime.py | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/sugar3/mime.py b/src/sugar3/mime.py
index 07d085e..70b4d2b 100644
--- a/src/sugar3/mime.py
+++ b/src/sugar3/mime.py
@@ -25,6 +25,8 @@ import os
 import logging
 import gettext
 
+from gi.repository import GdkPixbuf
+
 from sugar3 import _sugarbaseext
 
 _ = lambda msg: gettext.dgettext('sugar-base', msg)
@@ -35,6 +37,14 @@ GENERIC_TYPE_AUDIO = 'Audio'
 GENERIC_TYPE_VIDEO = 'Video'
 GENERIC_TYPE_LINK = 'Link'
 
+
+def _get_supported_image_mime_types():
+mime_types = []
+for image_format in GdkPixbuf.Pixbuf.get_formats():
+mime_types.extend(image_format.get_mime_types())
+return mime_types
+
+
 _extensions = {}
 _globs_timestamps = []
 _generic_types = [
@@ -51,7 +61,7 @@ _generic_types = [
 'id': GENERIC_TYPE_IMAGE,
 'name': _('Image'),
 'icon': 'image-x-generic',
-'types': ['image/png', 'image/gif', 'image/jpeg'],
+'types': _get_supported_image_mime_types(),
 },
 {
 'id': GENERIC_TYPE_AUDIO,
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar] Connect the clear-clicked signal in the ObjectChooser listview

2012-08-31 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/journal/objectchooser.py | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/jarabe/journal/objectchooser.py 
b/src/jarabe/journal/objectchooser.py
index 175aa0f..f658345 100644
--- a/src/jarabe/journal/objectchooser.py
+++ b/src/jarabe/journal/objectchooser.py
@@ -85,6 +85,8 @@ class ObjectChooser(gtk.Window):
 
 self._list_view = ChooserListView()
 self._list_view.connect('entry-activated', self.__entry_activated_cb)
+self._list_view.connect('clear-clicked', self.__clear_clicked_cb)
+
 vbox.pack_start(self._list_view)
 self._list_view.show()
 
@@ -135,6 +137,9 @@ class ObjectChooser(gtk.Window):
 visible = event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED
 self._list_view.set_is_visible(visible)
 
+def __clear_clicked_cb(self, list_view):
+self._toolbar.clear_query()
+
 
 class TitleBox(VolumesToolbar):
 __gtype_name__ = 'TitleBox'
-- 
1.7.11.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk3] Set default python encoding to utf-8

2012-08-27 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

As spoted by Daniel Narvaez in [1], pygi does not set the default encoding
anymore as the old gtk did. This change break ported activities.
The change in gtk was discussed upstream here [2]
A better solution will be implemented when we port to python 3,
when we will be able to use real unicode strings.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

[1] http://lists.sugarlabs.org/archive/sugar-devel/2012-August/038993.html
[2] https://bugzilla.gnome.org/show_bug.cgi?id=681915
---
 bin/sugar-activity | 5 +
 1 file changed, 5 insertions(+)

diff --git a/bin/sugar-activity b/bin/sugar-activity
index 5aef1ae..839174a 100644
--- a/bin/sugar-activity
+++ b/bin/sugar-activity
@@ -18,6 +18,11 @@
 
 import os
 import sys
+# Change the default encoding to avoid UnicodeDecodeError
+# http://lists.sugarlabs.org/archive/sugar-devel/2012-August/038928.html
+reload(sys)
+sys.setdefaultencoding('utf-8')
+
 import gettext
 from optparse import OptionParser
 
-- 
1.7.11.2

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH sugar-toolkit] Don't cache window size in palettewindow invoker

2012-08-23 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The screen size can change, by example when the screen rotate,
and the stored values are not useful anymore.
Without this patch the device icons palettes in the Journal
or in the frame are not displayed if the screen is rotated
to right or left.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar/graphics/palettewindow.py | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/src/sugar/graphics/palettewindow.py 
b/src/sugar/graphics/palettewindow.py
index 5281e54..a19db62 100644
--- a/src/sugar/graphics/palettewindow.py
+++ b/src/sugar/graphics/palettewindow.py
@@ -453,8 +453,6 @@ class Invoker(gobject.GObject):
 
 self.parent = None
 
-self._screen_area = gtk.gdk.Rectangle(0, 0, gtk.gdk.screen_width(),
-  gtk.gdk.screen_height())
 self._position_hint = self.ANCHORED
 self._cursor_x = -1
 self._cursor_y = -1
@@ -502,20 +500,17 @@ class Invoker(gobject.GObject):
  palette_width, palette_height)
 
 def _in_screen(self, rect):
-return rect.x = self._screen_area.x and \
-   rect.y = self._screen_area.y and \
-   rect.x + rect.width = self._screen_area.width and \
-   rect.y + rect.height = self._screen_area.height
+return rect.x = 0 and rect.y = 0 and \
+   rect.x + rect.width = gtk.gdk.screen_width() and \
+   rect.y + rect.height = gtk.gdk.screen_height()
 
 def _get_area_in_screen(self, rect):
 Return area of rectangle visible in the screen
 
-x1 = max(rect.x, self._screen_area.x)
-y1 = max(rect.y, self._screen_area.y)
-x2 = min(rect.x + rect.width,
-self._screen_area.x + self._screen_area.width)
-y2 = min(rect.y + rect.height,
-self._screen_area.y + self._screen_area.height)
+x1 = max(rect.x, 0)
+y1 = max(rect.y, 0)
+x2 = min(rect.x + rect.width, gtk.gdk.screen_width())
+y2 = min(rect.y + rect.height, gtk.gdk.screen_height())
 
 return (x2 - x1) * (y2 - y1)
 
@@ -545,8 +540,8 @@ class Invoker(gobject.GObject):
 rect.x = max(0, rect.x)
 rect.y = max(0, rect.y)
 
-rect.x = min(rect.x, self._screen_area.width - rect.width)
-rect.y = min(rect.y, self._screen_area.height - rect.height)
+rect.x = min(rect.x, gtk.gdk.screen_width() - rect.width)
+rect.y = min(rect.y, gtk.gdk.screen_height() - rect.height)
 
 return rect
 
@@ -572,7 +567,8 @@ class Invoker(gobject.GObject):
 iv = best_alignment[3]
 
 rect = self.get_rect()
-screen_area = self._screen_area
+screen_area = gtk.gdk.Rectangle(0, 0, gtk.gdk.screen_width(),
+  gtk.gdk.screen_height())
 
 if best_alignment in self.LEFT or best_alignment in self.RIGHT:
 dtop = rect.y - screen_area.y
-- 
1.7.11.2

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-artwork] Apply theme in RadioToolButton

2012-08-13 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This issue is displayed in the activities ported to gtk3,
Finance SL#3739, Jukebox SL#3765, and Paint.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 gtk3/theme/gtk-widgets.css.em | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gtk3/theme/gtk-widgets.css.em b/gtk3/theme/gtk-widgets.css.em
index f3e4fde..62ca475 100644
--- a/gtk3/theme/gtk-widgets.css.em
+++ b/gtk3/theme/gtk-widgets.css.em
@@ -521,6 +521,7 @@ background-color: @black;
 }
 
 .toolbar GtkToolButton .button,
+.toolbar SugarRadioToolButton *,
 SugarPaletteWindowWidget SugarRadioToolButton *,
 SugarPaletteWindowWidget GtkToolButton .button{
 background-color: transparent;
@@ -533,6 +534,7 @@ SugarPaletteWindowWidget GtkToolButton .button:prelight {
 background-color: @black;
 }
 
+.toolbar SugarRadioToolButton *:active,
 SugarPaletteWindowWidget SugarRadioToolButton *:active {
 background-color: @button_grey;
 border-radius: $(toolbutton_padding)px;
-- 
1.7.11.2

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk3] Replace signal used in UnfullscreenButton to enable use with touch - SL #3798

2012-08-09 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Use clicked instead of button-pressed, because this is not triggered
by touch device.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/graphics/window.py | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/sugar3/graphics/window.py b/src/sugar3/graphics/window.py
index 2d9764d..23a8d4f 100644
--- a/src/sugar3/graphics/window.py
+++ b/src/sugar3/graphics/window.py
@@ -65,8 +65,8 @@ class UnfullscreenButton(Gtk.Window):
 self._button.show()
 self.add(self._button)
 
-def connect_button_press(self, cb):
-self._button.connect('button-press-event', cb)
+def connect_button_clicked(self, cb):
+self._button.connect('clicked', cb)
 
 def _reposition(self):
 x = Gdk.Screen.width() - self._width
@@ -114,8 +114,8 @@ class Window(Gtk.Window):
 self._is_fullscreen = False
 self._unfullscreen_button = UnfullscreenButton()
 self._unfullscreen_button.set_transient_for(self)
-self._unfullscreen_button.connect_button_press(
-self.__unfullscreen_button_pressed)
+self._unfullscreen_button.connect_button_clicked(
+self.__unfullscreen_button_clicked)
 self._unfullscreen_button_timeout_id = None
 
 def reveal(self):
@@ -253,7 +253,7 @@ class Window(Gtk.Window):
 return True
 return False
 
-def __unfullscreen_button_pressed(self, widget, event):
+def __unfullscreen_button_clicked(self, button):
 self.unfullscreen()
 
 def __motion_notify_cb(self, widget, event):
-- 
1.7.11.2

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [sugar-toolkit-gtk3] Finish the port of ColorToolButton to gtk3

2012-08-07 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch solves the following problems:

* API changed in the drag and drop code in Gtk
* Changes in the way to get color information from the theme.
* The internal button was not visible.

Signed-of-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/graphics/colorbutton.py | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/src/sugar3/graphics/colorbutton.py 
b/src/sugar3/graphics/colorbutton.py
index c21da47..3b847b3 100644
--- a/src/sugar3/graphics/colorbutton.py
+++ b/src/sugar3/graphics/colorbutton.py
@@ -64,20 +64,19 @@ class _ColorButton(Gtk.Button):
 GObject.GObject.__init__(self, **kwargs)
 
 if self._accept_drag:
-Gtk.drag_dest_set(self, Gtk.DEST_DEFAULT_MOTION |
-   Gtk.DEST_DEFAULT_HIGHLIGHT |
-   Gtk.DEST_DEFAULT_DROP,
-   [('application/x-color', 0, 0)],
-   Gdk.DragAction.COPY)
-self.drag_source_set(Gdk.EventMask.BUTTON1_MASK | 
Gdk.EventMask.BUTTON3_MASK,
- [('application/x-color', 0, 0)],
- Gdk.DragAction.COPY)
+self.drag_dest_set(Gtk.DestDefaults.MOTION |
+Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP,
+[Gtk.TargetEntry.new('application/x-color', 0, 0)],
+Gdk.DragAction.COPY)
+self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK | \
+Gdk.ModifierType.BUTTON3_MASK,
+[Gtk.TargetEntry.new('application/x-color', 0, 0)],
+Gdk.DragAction.COPY)
 self.connect('drag_data_received', self.__drag_data_received_cb)
 self.connect('drag_data_get', self.__drag_data_get_cb)
 
 self._preview.fill_color = get_svg_color_string(self._color)
-self._preview.stroke_color = \
-get_svg_color_string(self.style.fg[Gtk.StateType.NORMAL])
+self._preview.stroke_color = self._get_fg_style_color_str()
 self.set_image(self._preview)
 
 if self._has_palette and self._has_invoker:
@@ -103,8 +102,14 @@ class _ColorButton(Gtk.Button):
 self.color = self._palette.color
 
 def do_style_set(self, previous_style):
-self._preview.stroke_color = \
-get_svg_color_string(self.style.fg[Gtk.StateType.NORMAL])
+self._preview.stroke_color = self._get_fg_style_color_str()
+
+def _get_fg_style_color_str(self):
+context = self.get_style_context()
+fg_color = context.get_color(Gtk.StateType.NORMAL)
+# the color components are stored as float values between 0.0 and 1.0
+return '#%.2X%.2X%.2X' % (fg_color.red * 255, fg_color.green * 255,
+  fg_color.blue * 255)
 
 def do_clicked(self):
 if self._palette:
@@ -438,6 +443,7 @@ class ColorToolButton(Gtk.ToolItem):
 # Replace it with a ColorButton
 color_button = _ColorButton(icon_name=icon_name, has_invoker=False)
 self.add(color_button)
+color_button.show()
 
 # The following is so that the behaviour on the toolbar is correct.
 color_button.set_relief(Gtk.ReliefStyle.NONE)
-- 
1.7.11.2

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar-toolkit-gtk3] ActivityButton should handle the case of activities without metadata

2012-05-14 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/activity/widgets.py |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/sugar3/activity/widgets.py b/src/sugar3/activity/widgets.py
index 97450f2..e2b7728 100644
--- a/src/sugar3/activity/widgets.py
+++ b/src/sugar3/activity/widgets.py
@@ -60,7 +60,8 @@ class ActivityButton(ToolButton):
 self.set_icon_widget(icon)
 icon.show()
 
-self.props.tooltip = activity.metadata['title']
+if activity.metadata:
+self.props.tooltip = activity.metadata['title']
 activity.metadata.connect('updated', self.__jobject_updated_cb)
 
 def __jobject_updated_cb(self, jobject):
-- 
1.7.10.1

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar-toolkit-gtk3] ActivityButton should handle the case of activities without metadata

2012-05-14 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

We already manage this cae in the icon creation but not when we set
the button tooltip

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

---

v2: Improve description.
Do not try to connect the 'updated' signal.
---
 src/sugar3/activity/widgets.py |5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/sugar3/activity/widgets.py b/src/sugar3/activity/widgets.py
index 97450f2..c7683cf 100644
--- a/src/sugar3/activity/widgets.py
+++ b/src/sugar3/activity/widgets.py
@@ -60,8 +60,9 @@ class ActivityButton(ToolButton):
 self.set_icon_widget(icon)
 icon.show()
 
-self.props.tooltip = activity.metadata['title']
-activity.metadata.connect('updated', self.__jobject_updated_cb)
+if activity.metadata:
+self.props.tooltip = activity.metadata['title']
+activity.metadata.connect('updated', self.__jobject_updated_cb)
 
 def __jobject_updated_cb(self, jobject):
 self.props.tooltip = jobject['title']
-- 
1.7.10.1

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar] Inhibit power suspend while playing text to speech - OLPC #11830

2012-05-10 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

To avoid stoping playing the text when the xo go to sleep.
This patch creates a file in /var/run/powerd-inhibit-suspend/
and remove it when finish. Is the same technique used in activities
(the code is copied from Distance activity) but we need decide
if is the right thing to do in sugar.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

---

v2: Remove ohmd code
v3: Implemented changes according to James review.
---
 src/jarabe/model/speech.py |   43 +--
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/src/jarabe/model/speech.py b/src/jarabe/model/speech.py
index 1cb0ad4..533fec2 100644
--- a/src/jarabe/model/speech.py
+++ b/src/jarabe/model/speech.py
@@ -30,6 +30,10 @@ DEFAULT_RATE = 0
 
 _speech_manager = None
 
+# directory exists if powerd is running.  create a file here,
+# named after our pid, to inhibit suspend.
+POWERD_INHIBIT_DIR = '/var/run/powerd-inhibit-suspend'
+
 
 class SpeechManager(gobject.GObject):
 
@@ -137,8 +141,10 @@ class _GstSpeechPlayer(gobject.GObject):
 def __init__(self):
 gobject.GObject.__init__(self)
 self._pipeline = None
+self.using_powerd = self._verify_powerd_directory()
 
 def restart_sound_device(self):
+self._inhibit_suspend()
 if self._pipeline is None:
 logging.debug('Trying to restart not initialized sound device')
 return
@@ -147,6 +153,7 @@ class _GstSpeechPlayer(gobject.GObject):
 self.emit('play')
 
 def pause_sound_device(self):
+self._allow_suspend()
 if self._pipeline is None:
 return
 
@@ -154,6 +161,7 @@ class _GstSpeechPlayer(gobject.GObject):
 self.emit('pause')
 
 def stop_sound_device(self):
+self._allow_suspend()
 if self._pipeline is None:
 return
 
@@ -172,12 +180,9 @@ class _GstSpeechPlayer(gobject.GObject):
 bus.connect('message', self.__pipe_message_cb)
 
 def __pipe_message_cb(self, bus, message):
-if message.type == gst.MESSAGE_EOS:
-self._pipeline.set_state(gst.STATE_NULL)
-self.emit('stop')
-elif message.type == gst.MESSAGE_ERROR:
-self._pipeline.set_state(gst.STATE_NULL)
-self.emit('stop')
+if message.type == gst.MESSAGE_EOS or \
+message.type == gst.MESSAGE_ERROR:
+self.stop_sound_device()
 
 def speak(self, pitch, rate, voice_name, text):
 # TODO workaround for http://bugs.sugarlabs.org/ticket/1801
@@ -223,6 +228,32 @@ class _GstSpeechPlayer(gobject.GObject):
 locale, best)
 return best
 
+def _verify_powerd_directory(self):
+using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK)
+logging.debug(using_powerd: %d, using_powerd)
+return using_powerd
+
+def _inhibit_suspend(self):
+if self.using_powerd:
+flag_file_name = self._powerd_flag_name()
+try:
+file(flag_file_name, 'w').write('')
+logging.debug(inhibit_suspend file is %s, flag_file_name)
+except IOError:
+pass
+
+def _allow_suspend(self):
+if self.using_powerd:
+flag_file_name = self._powerd_flag_name()
+try:
+os.unlink(flag_file_name)
+logging.debug(allow_suspend unlinking %s, flag_file_name)
+except IOError:
+pass
+
+def _powerd_flag_name(self):
+return POWERD_INHIBIT_DIR + /%u % os.getpid()
+
 
 def get_speech_manager():
 global _speech_manager
-- 
1.7.10.1

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar] Inhibit power suspend while playing text to speech - OLPC #11830

2012-05-09 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

To avoid stoping playing the text when the xo go to sleep.
This patch creates a file in /var/run/powerd-inhibit-suspend/
and remove it when finish. Is the same technique used in activities
(the code is copied from Distance activity) but we need decide
if is the right thing to do in sugar.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/model/speech.py |   69 
 1 file changed, 63 insertions(+), 6 deletions(-)

diff --git a/src/jarabe/model/speech.py b/src/jarabe/model/speech.py
index 1cb0ad4..24f4152 100644
--- a/src/jarabe/model/speech.py
+++ b/src/jarabe/model/speech.py
@@ -21,6 +21,7 @@ import gconf
 import gst
 import gtk
 import gobject
+import dbus
 
 
 DEFAULT_PITCH = 0
@@ -30,6 +31,10 @@ DEFAULT_RATE = 0
 
 _speech_manager = None
 
+# directory exists if powerd is running.  create a file here,
+# named after our pid, to inhibit suspend.
+POWERD_INHIBIT_DIR = '/var/run/powerd-inhibit-suspend'
+
 
 class SpeechManager(gobject.GObject):
 
@@ -138,7 +143,20 @@ class _GstSpeechPlayer(gobject.GObject):
 gobject.GObject.__init__(self)
 self._pipeline = None
 
+self.using_powerd = False
+if not self.powerd_running():
+try:
+bus = dbus.SystemBus()
+proxy = bus.get_object('org.freedesktop.ohm',
+   '/org/freedesktop/ohm/Keystore')
+self.ohm_keystore = dbus.Interface(
+proxy, 'org.freedesktop.ohm.Keystore')
+except dbus.DBusException, e:
+logging.warning(Error setting OHM inhibit: %s, e)
+self.ohm_keystore = None
+
 def restart_sound_device(self):
+self._inhibit_suspend()
 if self._pipeline is None:
 logging.debug('Trying to restart not initialized sound device')
 return
@@ -147,6 +165,7 @@ class _GstSpeechPlayer(gobject.GObject):
 self.emit('play')
 
 def pause_sound_device(self):
+self._allow_suspend()
 if self._pipeline is None:
 return
 
@@ -154,6 +173,7 @@ class _GstSpeechPlayer(gobject.GObject):
 self.emit('pause')
 
 def stop_sound_device(self):
+self._allow_suspend()
 if self._pipeline is None:
 return
 
@@ -172,12 +192,9 @@ class _GstSpeechPlayer(gobject.GObject):
 bus.connect('message', self.__pipe_message_cb)
 
 def __pipe_message_cb(self, bus, message):
-if message.type == gst.MESSAGE_EOS:
-self._pipeline.set_state(gst.STATE_NULL)
-self.emit('stop')
-elif message.type == gst.MESSAGE_ERROR:
-self._pipeline.set_state(gst.STATE_NULL)
-self.emit('stop')
+if message.type == gst.MESSAGE_EOS or \
+message.type == gst.MESSAGE_ERROR:
+self.stop_sound_device()
 
 def speak(self, pitch, rate, voice_name, text):
 # TODO workaround for http://bugs.sugarlabs.org/ticket/1801
@@ -223,6 +240,46 @@ class _GstSpeechPlayer(gobject.GObject):
 locale, best)
 return best
 
+def powerd_running(self):
+self.using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK)
+logging.debug(using_powerd: %d, self.using_powerd)
+return self.using_powerd
+
+def _inhibit_suspend(self):
+if self.using_powerd:
+fd = open(POWERD_INHIBIT_DIR + /%u % os.getpid(), 'w')
+logging.debug(inhibit_suspend file is %s % \
+   POWERD_INHIBIT_DIR + /%u % os.getpid())
+fd.close()
+return True
+
+if self.ohm_keystore is not None:
+try:
+self.ohm_keystore.SetKey('suspend.inhibit', 1)
+return self.ohm_keystore.GetKey('suspend.inhibit')
+except dbus.exceptions.DBusException:
+logging.warning(failed to inhibit suspend)
+return False
+else:
+return False
+
+def _allow_suspend(self):
+if self.using_powerd:
+os.unlink(POWERD_INHIBIT_DIR + /%u % os.getpid())
+logging.debug(allow_suspend unlinking %s % \
+   POWERD_INHIBIT_DIR + /%u % os.getpid())
+return True
+
+if self.ohm_keystore is not None:
+try:
+self.ohm_keystore.SetKey('suspend.inhibit', 0)
+return self.ohm_keystore.GetKey('suspend.inhibit')
+except dbus.exceptions.DBusException:
+logging.error(failed to allow suspend)
+return False
+else:
+return False
+
 
 def get_speech_manager():
 global _speech_manager
-- 
1.7.10.1

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar] Inhibit power suspend while playing text to speech - OLPC #11830

2012-05-09 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

To avoid stoping playing the text when the xo go to sleep.
This patch creates a file in /var/run/powerd-inhibit-suspend/
and remove it when finish. Is the same technique used in activities
(the code is copied from Distance activity) but we need decide
if is the right thing to do in sugar.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

---

v2: Remove ohmd code
---
 src/jarabe/model/speech.py |   37 +++--
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/src/jarabe/model/speech.py b/src/jarabe/model/speech.py
index 1cb0ad4..f07171c 100644
--- a/src/jarabe/model/speech.py
+++ b/src/jarabe/model/speech.py
@@ -30,6 +30,10 @@ DEFAULT_RATE = 0
 
 _speech_manager = None
 
+# directory exists if powerd is running.  create a file here,
+# named after our pid, to inhibit suspend.
+POWERD_INHIBIT_DIR = '/var/run/powerd-inhibit-suspend'
+
 
 class SpeechManager(gobject.GObject):
 
@@ -137,8 +141,10 @@ class _GstSpeechPlayer(gobject.GObject):
 def __init__(self):
 gobject.GObject.__init__(self)
 self._pipeline = None
+self.using_powerd = self._verify_powerd_running()
 
 def restart_sound_device(self):
+self._inhibit_suspend()
 if self._pipeline is None:
 logging.debug('Trying to restart not initialized sound device')
 return
@@ -147,6 +153,7 @@ class _GstSpeechPlayer(gobject.GObject):
 self.emit('play')
 
 def pause_sound_device(self):
+self._allow_suspend()
 if self._pipeline is None:
 return
 
@@ -154,6 +161,7 @@ class _GstSpeechPlayer(gobject.GObject):
 self.emit('pause')
 
 def stop_sound_device(self):
+self._allow_suspend()
 if self._pipeline is None:
 return
 
@@ -172,12 +180,9 @@ class _GstSpeechPlayer(gobject.GObject):
 bus.connect('message', self.__pipe_message_cb)
 
 def __pipe_message_cb(self, bus, message):
-if message.type == gst.MESSAGE_EOS:
-self._pipeline.set_state(gst.STATE_NULL)
-self.emit('stop')
-elif message.type == gst.MESSAGE_ERROR:
-self._pipeline.set_state(gst.STATE_NULL)
-self.emit('stop')
+if message.type == gst.MESSAGE_EOS or \
+message.type == gst.MESSAGE_ERROR:
+self.stop_sound_device()
 
 def speak(self, pitch, rate, voice_name, text):
 # TODO workaround for http://bugs.sugarlabs.org/ticket/1801
@@ -223,6 +228,26 @@ class _GstSpeechPlayer(gobject.GObject):
 locale, best)
 return best
 
+def _verify_powerd_running(self):
+self.using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK)
+logging.debug(using_powerd: %d, self.using_powerd)
+return self.using_powerd
+
+def _inhibit_suspend(self):
+if self.using_powerd:
+flag_file_name = POWERD_INHIBIT_DIR + /%u % os.getpid()
+if not os.path.exists(flag_file_name):
+fd = open(flag_file_name, 'w')
+logging.debug(inhibit_suspend file is %s % flag_file_name)
+fd.close()
+
+def _allow_suspend(self):
+if self.using_powerd:
+flag_file_name = POWERD_INHIBIT_DIR + /%u % os.getpid()
+if os.path.exists(flag_file_name):
+os.unlink(flag_file_name)
+logging.debug(allow_suspend unlinking %s % flag_file_name)
+
 
 def get_speech_manager():
 global _speech_manager
-- 
1.7.10.1

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar] Close audio device after text to speech - OLPC #11829

2012-05-04 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

In xo with alsa, if we keep opened the audio device after
doing tts, other activities can't use it.
We need close the device after the eof message is received,
because the message came a little before the sound has finished.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/model/speech.py |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/jarabe/model/speech.py b/src/jarabe/model/speech.py
index ffc108c..46ce483 100644
--- a/src/jarabe/model/speech.py
+++ b/src/jarabe/model/speech.py
@@ -155,10 +155,11 @@ class _GstSpeechPlayer(gobject.GObject):
 
 def stop_sound_device(self):
 if self._pipeline is None:
-return
+return False
 
 self._pipeline.set_state(gst.STATE_NULL)
 self.emit('stop')
+return False
 
 def make_pipeline(self, command):
 if self._pipeline is not None:
@@ -174,6 +175,7 @@ class _GstSpeechPlayer(gobject.GObject):
 def __pipe_message_cb(self, bus, message):
 if message.structure.get_name() == 'espeak-mark' and \
 message.structure['mark'] == 'end':
+gobject.timeout_add_seconds(1, self.stop_sound_device)
 self.emit('stop')
 
 def speak(self, pitch, rate, voice_name, text):
-- 
1.7.10

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Add the DescriptionItem if available

2012-04-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 activity.py |8 
 1 file changed, 8 insertions(+)

diff --git a/activity.py b/activity.py
index a7f8730..ffc9241 100644
--- a/activity.py
+++ b/activity.py
@@ -50,6 +50,14 @@ class HelloWorldActivity(activity.Activity):
 toolbar_box.toolbar.insert(title_entry, -1)
 title_entry.show()
 
+try:
+from sugar3.activity.widgets import DescriptionItem
+description_item = DescriptionItem(self)
+toolbar_box.toolbar.insert(description_item, -1)
+description_item.show()
+except:
+pass
+
 share_button = ShareButton(self)
 toolbar_box.toolbar.insert(share_button, -1)
 share_button.show()
-- 
1.7.10

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Add description item to the toolbar if available - SL# 3525

2012-04-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The activity have a custom toolbar, then need add the DescriptionItem
to implement the feature Write to Journal Anytime

http://wiki.sugarlabs.org/go/Features/Write_to_journal_anytime

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 activity.py |8 
 1 file changed, 8 insertions(+)

diff --git a/activity.py b/activity.py
index b885842..34a0e68 100644
--- a/activity.py
+++ b/activity.py
@@ -67,6 +67,14 @@ class Chat(activity.Activity):
 toolbar_box.toolbar.insert(ActivityButton(self), -1)
 toolbar_box.toolbar.insert(TitleEntry(self), -1)
 
+try:
+from sugar.activity.widgets import DescriptionItem
+description_item = DescriptionItem(self)
+toolbar_box.toolbar.insert(description_item, -1)
+description_item.show()
+except:
+pass
+
 share_button = ShareButton(self)
 toolbar_box.toolbar.insert(share_button, -1)
 
-- 
1.7.10

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Add description item to the toolbar if available - SL# 3525

2012-04-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The activity have a custom toolbar, then need add the DescriptionItem
to implement the feature Write to Journal Anytime

http://wiki.sugarlabs.org/go/Features/Write_to_journal_anytime

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 activity.py |8 
 1 file changed, 8 insertions(+)

diff --git a/activity.py b/activity.py
index 306b081..6660fa7 100644
--- a/activity.py
+++ b/activity.py
@@ -66,6 +66,14 @@ class StopWatchActivity(Activity):
 toolbar_box.toolbar.insert(title_entry, -1)
 title_entry.show()
 
+try:
+from sugar.activity.widgets import DescriptionItem
+description_item = DescriptionItem(self)
+toolbar_box.toolbar.insert(description_item, -1)
+description_item.show()
+except:
+pass
+
 share_button = ShareButton(self)
 toolbar_box.toolbar.insert(share_button, -1)
 share_button.show()
-- 
1.7.10

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH TamTamMini] Add description item to the toolbar if available - SL# 3525

2012-04-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The activity have a custom toolbar, then need add the DescriptionItem
to implement the feature Write to Journal Anytime

http://wiki.sugarlabs.org/go/Features/Write_to_journal_anytime

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 TamTamMini.py |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/TamTamMini.py b/TamTamMini.py
index 02d614d..5d94cc3 100644
--- a/TamTamMini.py
+++ b/TamTamMini.py
@@ -76,6 +76,17 @@ class TamTamMini(activity.Activity):
 self.toolbox = ToolbarBox()
 self.toolbox.toolbar.insert(widgets.ActivityButton(self), -1)
 self.toolbox.toolbar.insert(widgets.TitleEntry(self), -1)
+
+try:
+from sugar.activity.widgets import DescriptionItem
+except ImportError:
+   logging.debug('DescriptionItem button is not available,' +
+'toolkit version  0.96')
+else:
+description_item = DescriptionItem(self)
+self.toolbox.toolbar.insert(description_item, -1)
+description_item.show()
+
 self.toolbox.toolbar.insert(widgets.ShareButton(self), -1)
 else:
 self.toolbox = activity.ActivityToolbox(self)
-- 
1.7.10

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Words] Add description item to the toolbar if available - SL# 3525

2012-04-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The activity have a custom toolbar, then need add the DescriptionItem
to implement the feature Write to Journal Anytime

http://wiki.sugarlabs.org/go/Features/Write_to_journal_anytime

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 wordsactivity.py |   10 ++
 1 file changed, 10 insertions(+)

diff --git a/wordsactivity.py b/wordsactivity.py
index cfb8794..31666eb 100644
--- a/wordsactivity.py
+++ b/wordsactivity.py
@@ -79,6 +79,16 @@ class WordsActivity(activity.Activity):
 toolbar_box.toolbar.insert(title_entry, -1)
 title_entry.show()
 
+try:
+from sugar.activity.widgets import DescriptionItem
+except ImportError:
+   logging.debug('DescriptionItem button is not available,' +
+'toolkit version  0.96')
+else:
+description_item = DescriptionItem(self)
+toolbar_box.toolbar.insert(description_item, -1)
+description_item.show()
+
 share_button = ShareButton(self)
 toolbar_box.toolbar.insert(share_button, -1)
 share_button.show()
-- 
1.7.10

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Only add one time every object in the clipboard v5 - SL #3371

2012-04-24 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch change the behaviour of the clipboard tray,
every object is added only one time, if already exist,
the already added object is selected and a notification is displayed
(showing a flashing icon in the lower left corner).

A hash over the data in the object is used to determine if the object
is already present in the journal. When the object is a uri,
a md5sum is calculated over the file and the hash is done over the result.

We need check if the object is already in the clipboard
because a bad interaction between the clipboard in write and
the text to speech feature. See the ticket for more information.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org



v2: Select the already added object if needed, as sugested by Sascha.
v3: Show the notification when copy a already existing object, as sugested by 
Gary
v4: Check targets is not None
v5: Chages acording to Sascha review and management of uri from the journal
---
 src/jarabe/frame/clipboard.py|   22 +++---
 src/jarabe/frame/clipboardicon.py|   26 +++---
 src/jarabe/frame/clipboardpanelwindow.py |   34 +-
 3 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
index be2b902..f3da89f 100644
--- a/src/jarabe/frame/clipboard.py
+++ b/src/jarabe/frame/clipboard.py
@@ -36,7 +36,9 @@ class Clipboard(gobject.GObject):
 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-([int])),
+([long])),
+'object-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+([long])),
 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 }
@@ -51,9 +53,21 @@ class Clipboard(gobject.GObject):
 self._next_id += 1
 return self._next_id
 
-def add_object(self, name):
-logging.debug('Clipboard.add_object')
-object_id = self._get_next_object_id()
+def add_object(self, name, data_hash=None):
+ Add a object to the clipboard.
+data_hash is a long used to check if the object is already
+in the clipboard, generated with hash() over the data to be added.
+Return the object_id or None if the object is not added.
+
+logging.debug('Clipboard.add_object hash %s', data_hash)
+if data_hash is None:
+object_id = self._get_next_object_id()
+else:
+object_id = data_hash
+if object_id in self._objects:
+logging.debug('Duplicate entry, selecting previous entry instead')
+self.emit('object-selected', object_id)
+return None
 self._objects[object_id] = ClipboardObject(object_id, name)
 self.emit('object-added', self._objects[object_id])
 return object_id
diff --git a/src/jarabe/frame/clipboardicon.py 
b/src/jarabe/frame/clipboardicon.py
index aa72d8a..315cdaa 100644
--- a/src/jarabe/frame/clipboardicon.py
+++ b/src/jarabe/frame/clipboardicon.py
@@ -57,6 +57,7 @@ class ClipboardIcon(RadioToolButton):
 cb_service = clipboard.get_instance()
 cb_service.connect('object-state-changed',
self._object_state_changed_cb)
+cb_service.connect('object-selected', self._object_selected_cb)
 
 child = self.get_child()
 child.connect('drag_data_get', self._drag_data_get_cb)
@@ -128,17 +129,26 @@ class ClipboardIcon(RadioToolButton):
 # Clipboard object became complete. Make it the active one.
 if self._current_percent  100 and cb_object.get_percent() == 100:
 self.props.active = True
+self.show_notification()
 
-self._notif_icon = NotificationIcon()
-self._notif_icon.props.icon_name = self._icon.props.icon_name
-self._notif_icon.props.xo_color = \
-XoColor('%s,%s' % (self._icon.props.stroke_color,
-   self._icon.props.fill_color))
-frame = jarabe.frame.get_view()
-frame.add_notification(self._notif_icon,
-   gtk.CORNER_BOTTOM_LEFT)
 self._current_percent = cb_object.get_percent()
 
+def _object_selected_cb(self, cb_service, object_id):
+if object_id != self._cb_object.get_id():
+return
+self.props.active = True
+self.show_notification()
+logging.debug('ClipboardIcon: %r was selected', object_id)
+
+def show_notification(self):
+self._notif_icon = NotificationIcon()
+self._notif_icon.props.icon_name = self._icon.props.icon_name
+self._notif_icon.props.xo_color = \
+XoColor('%s,%s' % 

[Sugar-devel] [PATCH] When a object is removed from the clipboard try, select the last available v3 - SL #1266

2012-04-24 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

If the user remove a object from the clipboard,
the last available object should be selected,
and if no more objects are available, the clipboard should be cleaned.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
v2: If there no more objects in the try, clean the clipboard
v3: Changes suggested in review by Sascha.
---
 src/jarabe/frame/clipboard.py |4 
 src/jarabe/frame/clipboardtray.py |5 +
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
index f3da89f..3bdc7f2 100644
--- a/src/jarabe/frame/clipboard.py
+++ b/src/jarabe/frame/clipboard.py
@@ -21,6 +21,7 @@ import urlparse
 import tempfile
 
 import gobject
+import gtk
 
 from sugar import mime
 
@@ -94,6 +95,9 @@ class Clipboard(gobject.GObject):
 def delete_object(self, object_id):
 cb_object = self._objects.pop(object_id)
 cb_object.destroy()
+if not self._objects:
+gtk_clipboard = gtk.Clipboard()
+gtk_clipboard.clear()
 self.emit('object-deleted', object_id)
 logging.debug('Deleted object with object_id %r', object_id)
 
diff --git a/src/jarabe/frame/clipboardtray.py 
b/src/jarabe/frame/clipboardtray.py
index f49b799..37d5e1a 100644
--- a/src/jarabe/frame/clipboardtray.py
+++ b/src/jarabe/frame/clipboardtray.py
@@ -123,6 +123,11 @@ class ClipboardTray(tray.VTray):
 icon = self._icons[object_id]
 self.remove_item(icon)
 del self._icons[object_id]
+# select the last available icon
+if self._icons:
+last_icon = self.get_children()[-1]
+last_icon.props.active = True
+
 logging.debug('ClipboardTray: %r was deleted', object_id)
 
 def drag_motion_cb(self, widget, context, x, y, time):
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Handle missing gst-plugins-espeak gracefully - SL#3345

2012-04-24 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The text-to-speech support in Sugar (jarabe.model.speech) depends on
gst-plugins-espeak [1]. While Sugar continues to work properly in the
absence of gst-plugins-espeak, loading the corresponding components
(keyboard shortcut handler and Frame device icon) currently fails hard
and produces a traceback in the log. However TTS support is entirely
optional and the traceback suggests an unhandled system failure rather
than optional support not being available. Fix this by catching the
exception when accessing the SpeechManager and logging a warning
instead.

[1] https://wiki.sugarlabs.org/go/Activity_Team/gst-plugins-espeak

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 extensions/deviceicon/speech.py |7 +--
 extensions/globalkey/speech.py  |2 --
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
index 6b8f915..889d509 100644
--- a/extensions/deviceicon/speech.py
+++ b/extensions/deviceicon/speech.py
@@ -14,6 +14,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
+import logging
 from gettext import gettext as _
 
 import glib
@@ -31,7 +32,6 @@ from sugar.graphics import style
 from jarabe.frame.frameinvoker import FrameWidgetInvoker
 from jarabe.model import speech
 
-
 _ICON_NAME = 'microphone'
 
 
@@ -145,4 +145,7 @@ class SpeechPalette(Palette):
 
 
 def setup(tray):
-tray.add_device(SpeechDeviceView())
+try:
+tray.add_device(SpeechDeviceView())
+except:
+logging.warning('Text to speech no available. Missing dependencies')
diff --git a/extensions/globalkey/speech.py b/extensions/globalkey/speech.py
index 2879b69..c4374cd 100644
--- a/extensions/globalkey/speech.py
+++ b/extensions/globalkey/speech.py
@@ -14,8 +14,6 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-from jarabe.model import speech
-
 BOUND_KEYS = ['altshifts']
 
 
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Handle missing gst-plugins-espeak gracefully - SL#3345

2012-04-24 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The text-to-speech support in Sugar (jarabe.model.speech) depends on
gst-plugins-espeak [1]. While Sugar continues to work properly in the
absence of gst-plugins-espeak, loading the corresponding components
(keyboard shortcut handler and Frame device icon) currently fails hard
and produces a traceback in the log. However TTS support is entirely
optional and the traceback suggests an unhandled system failure rather
than optional support not being available. Fix this by catching the
exception when accessing the SpeechManager and logging a warning
instead.

[1] https://wiki.sugarlabs.org/go/Activity_Team/gst-plugins-espeak

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 extensions/deviceicon/speech.py |7 +--
 extensions/globalkey/speech.py  |3 +--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
index 6b8f915..889d509 100644
--- a/extensions/deviceicon/speech.py
+++ b/extensions/deviceicon/speech.py
@@ -14,6 +14,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
+import logging
 from gettext import gettext as _
 
 import glib
@@ -31,7 +32,6 @@ from sugar.graphics import style
 from jarabe.frame.frameinvoker import FrameWidgetInvoker
 from jarabe.model import speech
 
-
 _ICON_NAME = 'microphone'
 
 
@@ -145,4 +145,7 @@ class SpeechPalette(Palette):
 
 
 def setup(tray):
-tray.add_device(SpeechDeviceView())
+try:
+tray.add_device(SpeechDeviceView())
+except:
+logging.warning('Text to speech no available. Missing dependencies')
diff --git a/extensions/globalkey/speech.py b/extensions/globalkey/speech.py
index 2879b69..e47c778 100644
--- a/extensions/globalkey/speech.py
+++ b/extensions/globalkey/speech.py
@@ -14,10 +14,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-from jarabe.model import speech
-
 BOUND_KEYS = ['altshifts']
 
+from jarabe.model import speech
 
 def handle_key_press(key):
 manager = speech.get_speech_manager()
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Only add one time every object in the clipboard v3 - SL #3371

2012-04-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch change the behaviour of the clipboard tray,
every object is added only one time, if already exist,
the already added object is selected.
Is needed because a bad interaction between the clipboard in write and
the text to speech feature. See the ticket for more information.

v2: Select the already added object if needed, as sugested by Sasha.
v3: Show the notification when copy a already existing object, as sugested by 
Gary

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/clipboard.py|   17 +
 src/jarabe/frame/clipboardicon.py|   18 ++
 src/jarabe/frame/clipboardpanelwindow.py |5 -
 src/jarabe/frame/clipboardtray.py|7 +++
 4 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
index be2b902..ae1ceb9 100644
--- a/src/jarabe/frame/clipboard.py
+++ b/src/jarabe/frame/clipboard.py
@@ -36,7 +36,9 @@ class Clipboard(gobject.GObject):
 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-([int])),
+([long])),
+'object-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+([long])),
 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 }
@@ -51,9 +53,16 @@ class Clipboard(gobject.GObject):
 self._next_id += 1
 return self._next_id
 
-def add_object(self, name):
-logging.debug('Clipboard.add_object')
-object_id = self._get_next_object_id()
+def add_object(self, name, data_hash=None):
+logging.debug('Clipboard.add_object hash %s', data_hash)
+if data_hash is None:
+object_id = self._get_next_object_id()
+else:
+object_id = data_hash
+if object_id in self._objects:
+logging.debug('Object rejected, already exist')
+self.emit('object-selected', object_id)
+return None
 self._objects[object_id] = ClipboardObject(object_id, name)
 self.emit('object-added', self._objects[object_id])
 return object_id
diff --git a/src/jarabe/frame/clipboardicon.py 
b/src/jarabe/frame/clipboardicon.py
index aa72d8a..7bc4dc3 100644
--- a/src/jarabe/frame/clipboardicon.py
+++ b/src/jarabe/frame/clipboardicon.py
@@ -128,17 +128,19 @@ class ClipboardIcon(RadioToolButton):
 # Clipboard object became complete. Make it the active one.
 if self._current_percent  100 and cb_object.get_percent() == 100:
 self.props.active = True
+self.show_notification()
 
-self._notif_icon = NotificationIcon()
-self._notif_icon.props.icon_name = self._icon.props.icon_name
-self._notif_icon.props.xo_color = \
-XoColor('%s,%s' % (self._icon.props.stroke_color,
-   self._icon.props.fill_color))
-frame = jarabe.frame.get_view()
-frame.add_notification(self._notif_icon,
-   gtk.CORNER_BOTTOM_LEFT)
 self._current_percent = cb_object.get_percent()
 
+def show_notification(self):
+self._notif_icon = NotificationIcon()
+self._notif_icon.props.icon_name = self._icon.props.icon_name
+self._notif_icon.props.xo_color = \
+XoColor('%s,%s' % (self._icon.props.stroke_color,
+   self._icon.props.fill_color))
+frame = jarabe.frame.get_view()
+frame.add_notification(self._notif_icon, gtk.CORNER_BOTTOM_LEFT)
+
 def _drag_begin_cb(self, widget, context):
 # TODO: We should get the pixbuf from the icon, with colors, etc.
 icon_theme = gtk.icon_theme_get_default()
diff --git a/src/jarabe/frame/clipboardpanelwindow.py 
b/src/jarabe/frame/clipboardpanelwindow.py
index b73572e..28c5726 100644
--- a/src/jarabe/frame/clipboardpanelwindow.py
+++ b/src/jarabe/frame/clipboardpanelwindow.py
@@ -70,7 +70,10 @@ class ClipboardPanelWindow(FrameWindow):
 cb_selections.append(selection)
 
 if len(cb_selections)  0:
-key = cb_service.add_object(name=)
+key = cb_service.add_object(name=,
+data_hash=hash(selection.data))
+if key is None:
+return
 cb_service.set_object_percent(key, percent=0)
 for selection in cb_selections:
 self._add_selection(key, selection)
diff --git a/src/jarabe/frame/clipboardtray.py 
b/src/jarabe/frame/clipboardtray.py
index f49b799..f736295 100644
--- a/src/jarabe/frame/clipboardtray.py
+++ b/src/jarabe/frame/clipboardtray.py
@@ -70,6 +70,7 @@ class ClipboardTray(tray.VTray):
 cb_service = 

[Sugar-devel] [PATCH] When a object is removed from the clipboard try, select the last available v2 - SL #1266

2012-04-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

v2: If there no more objects in the try, clean the clipboard

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/clipboardtray.py |8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/frame/clipboardtray.py 
b/src/jarabe/frame/clipboardtray.py
index f736295..f6e7f94 100644
--- a/src/jarabe/frame/clipboardtray.py
+++ b/src/jarabe/frame/clipboardtray.py
@@ -124,6 +124,14 @@ class ClipboardTray(tray.VTray):
 icon = self._icons[object_id]
 self.remove_item(icon)
 del self._icons[object_id]
+# select the last available icon
+if len(self._icons)  0:
+n_icons = len(self.get_children())
+last_icon = self.get_children()[n_icons - 1]
+last_icon.props.active = True
+else:
+gtk_clipboard = gtk.Clipboard()
+gtk_clipboard.clear()
 logging.debug('ClipboardTray: %r was deleted', object_id)
 
 def _object_selected_cb(self, cb_service, object_id):
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] When a object is removed from the clipboard try, select the last available v2 - SL #1266

2012-04-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

v2: If there no more objects in the try, clean the clipboard

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/clipboardtray.py |8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/frame/clipboardtray.py 
b/src/jarabe/frame/clipboardtray.py
index f736295..f6e7f94 100644
--- a/src/jarabe/frame/clipboardtray.py
+++ b/src/jarabe/frame/clipboardtray.py
@@ -124,6 +124,14 @@ class ClipboardTray(tray.VTray):
 icon = self._icons[object_id]
 self.remove_item(icon)
 del self._icons[object_id]
+# select the last available icon
+if len(self._icons)  0:
+n_icons = len(self.get_children())
+last_icon = self.get_children()[n_icons - 1]
+last_icon.props.active = True
+else:
+gtk_clipboard = gtk.Clipboard()
+gtk_clipboard.clear()
 logging.debug('ClipboardTray: %r was deleted', object_id)
 
 def _object_selected_cb(self, cb_service, object_id):
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Only add one time every object in the clipboard v4 - SL #3371

2012-04-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch change the behaviour of the clipboard tray,
every object is added only one time, if already exist,
the already added object is selected.
Is needed because a bad interaction between the clipboard in write and
the text to speech feature. See the ticket for more information.

v2: Select the already added object if needed, as sugested by Sasha.
v3: Show the notification when copy a already existing object, as sugested by 
Gary
v4: Check targets is not None

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/clipboard.py|   17 +
 src/jarabe/frame/clipboardicon.py|   18 ++
 src/jarabe/frame/clipboardpanelwindow.py |7 ++-
 src/jarabe/frame/clipboardtray.py|7 +++
 4 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
index be2b902..ae1ceb9 100644
--- a/src/jarabe/frame/clipboard.py
+++ b/src/jarabe/frame/clipboard.py
@@ -36,7 +36,9 @@ class Clipboard(gobject.GObject):
 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-([int])),
+([long])),
+'object-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+([long])),
 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 }
@@ -51,9 +53,16 @@ class Clipboard(gobject.GObject):
 self._next_id += 1
 return self._next_id
 
-def add_object(self, name):
-logging.debug('Clipboard.add_object')
-object_id = self._get_next_object_id()
+def add_object(self, name, data_hash=None):
+logging.debug('Clipboard.add_object hash %s', data_hash)
+if data_hash is None:
+object_id = self._get_next_object_id()
+else:
+object_id = data_hash
+if object_id in self._objects:
+logging.debug('Object rejected, already exist')
+self.emit('object-selected', object_id)
+return None
 self._objects[object_id] = ClipboardObject(object_id, name)
 self.emit('object-added', self._objects[object_id])
 return object_id
diff --git a/src/jarabe/frame/clipboardicon.py 
b/src/jarabe/frame/clipboardicon.py
index aa72d8a..7bc4dc3 100644
--- a/src/jarabe/frame/clipboardicon.py
+++ b/src/jarabe/frame/clipboardicon.py
@@ -128,17 +128,19 @@ class ClipboardIcon(RadioToolButton):
 # Clipboard object became complete. Make it the active one.
 if self._current_percent  100 and cb_object.get_percent() == 100:
 self.props.active = True
+self.show_notification()
 
-self._notif_icon = NotificationIcon()
-self._notif_icon.props.icon_name = self._icon.props.icon_name
-self._notif_icon.props.xo_color = \
-XoColor('%s,%s' % (self._icon.props.stroke_color,
-   self._icon.props.fill_color))
-frame = jarabe.frame.get_view()
-frame.add_notification(self._notif_icon,
-   gtk.CORNER_BOTTOM_LEFT)
 self._current_percent = cb_object.get_percent()
 
+def show_notification(self):
+self._notif_icon = NotificationIcon()
+self._notif_icon.props.icon_name = self._icon.props.icon_name
+self._notif_icon.props.xo_color = \
+XoColor('%s,%s' % (self._icon.props.stroke_color,
+   self._icon.props.fill_color))
+frame = jarabe.frame.get_view()
+frame.add_notification(self._notif_icon, gtk.CORNER_BOTTOM_LEFT)
+
 def _drag_begin_cb(self, widget, context):
 # TODO: We should get the pixbuf from the icon, with colors, etc.
 icon_theme = gtk.icon_theme_get_default()
diff --git a/src/jarabe/frame/clipboardpanelwindow.py 
b/src/jarabe/frame/clipboardpanelwindow.py
index b73572e..5865e4e 100644
--- a/src/jarabe/frame/clipboardpanelwindow.py
+++ b/src/jarabe/frame/clipboardpanelwindow.py
@@ -59,6 +59,8 @@ class ClipboardPanelWindow(FrameWindow):
 
 targets = x_clipboard.wait_for_targets()
 cb_selections = []
+if targets is None:
+return
 for target in targets:
 if target not in ('TIMESTAMP', 'TARGETS',
   'MULTIPLE', 'SAVE_TARGETS'):
@@ -70,7 +72,10 @@ class ClipboardPanelWindow(FrameWindow):
 cb_selections.append(selection)
 
 if len(cb_selections)  0:
-key = cb_service.add_object(name=)
+key = cb_service.add_object(name=,
+data_hash=hash(selection.data))
+if key is None:
+return
 cb_service.set_object_percent(key, percent=0)

[Sugar-devel] [PATCH] Only add one time every object in the clipboard v2 - SL #3371

2012-04-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch change the behaviour of the clipboard tray,
every object is added only one time, if already exist,
the already added object is selected.
Is needed because a bad interaction between the clipboard in write and
the text to speech feature. See the ticket for more information.

v2: Select the already added object if needed, as sugested by Sasha.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/clipboard.py|   17 +
 src/jarabe/frame/clipboardpanelwindow.py |5 -
 src/jarabe/frame/clipboardtray.py|6 ++
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
index be2b902..ae1ceb9 100644
--- a/src/jarabe/frame/clipboard.py
+++ b/src/jarabe/frame/clipboard.py
@@ -36,7 +36,9 @@ class Clipboard(gobject.GObject):
 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-([int])),
+([long])),
+'object-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+([long])),
 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
 ([object])),
 }
@@ -51,9 +53,16 @@ class Clipboard(gobject.GObject):
 self._next_id += 1
 return self._next_id
 
-def add_object(self, name):
-logging.debug('Clipboard.add_object')
-object_id = self._get_next_object_id()
+def add_object(self, name, data_hash=None):
+logging.debug('Clipboard.add_object hash %s', data_hash)
+if data_hash is None:
+object_id = self._get_next_object_id()
+else:
+object_id = data_hash
+if object_id in self._objects:
+logging.debug('Object rejected, already exist')
+self.emit('object-selected', object_id)
+return None
 self._objects[object_id] = ClipboardObject(object_id, name)
 self.emit('object-added', self._objects[object_id])
 return object_id
diff --git a/src/jarabe/frame/clipboardpanelwindow.py 
b/src/jarabe/frame/clipboardpanelwindow.py
index b73572e..28c5726 100644
--- a/src/jarabe/frame/clipboardpanelwindow.py
+++ b/src/jarabe/frame/clipboardpanelwindow.py
@@ -70,7 +70,10 @@ class ClipboardPanelWindow(FrameWindow):
 cb_selections.append(selection)
 
 if len(cb_selections)  0:
-key = cb_service.add_object(name=)
+key = cb_service.add_object(name=,
+data_hash=hash(selection.data))
+if key is None:
+return
 cb_service.set_object_percent(key, percent=0)
 for selection in cb_selections:
 self._add_selection(key, selection)
diff --git a/src/jarabe/frame/clipboardtray.py 
b/src/jarabe/frame/clipboardtray.py
index f49b799..e78ef4a 100644
--- a/src/jarabe/frame/clipboardtray.py
+++ b/src/jarabe/frame/clipboardtray.py
@@ -70,6 +70,7 @@ class ClipboardTray(tray.VTray):
 cb_service = clipboard.get_instance()
 cb_service.connect('object-added', self._object_added_cb)
 cb_service.connect('object-deleted', self._object_deleted_cb)
+cb_service.connect('object-selected', self._object_selected_cb)
 
 def owns_clipboard(self):
 for icon in self._icons.values():
@@ -125,6 +126,11 @@ class ClipboardTray(tray.VTray):
 del self._icons[object_id]
 logging.debug('ClipboardTray: %r was deleted', object_id)
 
+def _object_selected_cb(self, cb_service, object_id):
+icon = self._icons[object_id]
+icon.props.active = True
+logging.debug('ClipboardTray: %r was activated', object_id)
+
 def drag_motion_cb(self, widget, context, x, y, time):
 logging.debug('ClipboardTray._drag_motion_cb')
 
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] When a object is removed from the clipboard try, select the last available - SL #1266

2012-04-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/clipboardtray.py |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/frame/clipboardtray.py 
b/src/jarabe/frame/clipboardtray.py
index e78ef4a..b1426c4 100644
--- a/src/jarabe/frame/clipboardtray.py
+++ b/src/jarabe/frame/clipboardtray.py
@@ -124,6 +124,11 @@ class ClipboardTray(tray.VTray):
 icon = self._icons[object_id]
 self.remove_item(icon)
 del self._icons[object_id]
+# select the last available icon
+if len(self._icons)  0:
+n_icons = len(self.get_children())
+last_icon = self.get_children()[n_icons - 1]
+last_icon.props.active = True
 logging.debug('ClipboardTray: %r was deleted', object_id)
 
 def _object_selected_cb(self, cb_service, object_id):
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH 1/2] Backport Add DescriptionEntry to the activity sub-toolbar from sugar-toolkit-gtk3

2012-04-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This is the implementation of the 'Write to Journal anytime' feature [1].

The patch itself adds a DescriptionItem to the activity
sub-toolbar to make editing a Journal entry description
from within the activity possible. The code has the same
error handling as the TitleEntry.

After talking with teachers and the learning team,
I found they are very excited about this feature.
Doing this change we will have a more consistent experience
in the activities at the release of sugar 0.96 too.

The original patch was done by Simon Schampijer si...@laptop.org
and Walter Bender walter.ben...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

[1] http://wiki.sugarlabs.org/go/Features/Write_to_journal_anytime
---
 src/sugar/activity/widgets.py |   71 +
 1 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py
index e5c4063..ab75cd6 100644
--- a/src/sugar/activity/widgets.py
+++ b/src/sugar/activity/widgets.py
@@ -28,6 +28,7 @@ from sugar.graphics.toolbox import Toolbox
 from sugar.graphics.xocolor import XoColor
 from sugar.graphics.icon import Icon
 from sugar.bundle.activitybundle import ActivityBundle
+from sugar.graphics import style
 
 
 _ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
@@ -235,6 +236,71 @@ class TitleEntry(gtk.ToolItem):
 shared_activity.props.name = title
 
 
+class DescriptionItem(gtk.ToolItem):
+
+def __init__(self, activity, **kwargs):
+gtk.ToolItem.__init__(self)
+
+description_button = ToolButton('edit-description')
+description_button.show()
+description_button.set_tooltip(_('Description'))
+self._palette = description_button.get_palette()
+
+description_box = gtk.HBox()
+sw = gtk.ScrolledWindow()
+sw.set_size_request(int(gtk.gdk.screen_width() / 2),
+2 * style.GRID_CELL_SIZE)
+sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+self._text_view = gtk.TextView()
+self._text_view.set_left_margin(style.DEFAULT_PADDING)
+self._text_view.set_right_margin(style.DEFAULT_PADDING)
+text_buffer = gtk.TextBuffer()
+if 'description' in activity.metadata:
+text_buffer.set_text(activity.metadata['description'])
+self._text_view.set_buffer(text_buffer)
+self._text_view.connect('focus-out-event',
+   self.__description_changed_cb, activity)
+sw.add(self._text_view)
+description_box.pack_start(sw, False, True, 0)
+self._palette.set_content(description_box)
+description_box.show_all()
+
+self.add(description_button)
+description_button.connect('clicked',
+   self.__description_button_clicked_cb)
+
+activity.metadata.connect('updated', self.__jobject_updated_cb)
+
+def _get_text_from_buffer(self):
+buf = self._text_view.get_buffer()
+start_iter = buf.get_start_iter()
+end_iter = buf.get_end_iter()
+return buf.get_text(start_iter, end_iter, False)
+
+def __jobject_updated_cb(self, jobject):
+if self._text_view.has_focus():
+return
+if 'description' not in jobject:
+return
+if self._get_text_from_buffer() == jobject['description']:
+return
+buf = self._text_view.get_buffer()
+buf.set_text(jobject['description'])
+
+def __description_button_clicked_cb(self, button):
+self._palette.popup(immediate=True, state=1)
+
+def __description_changed_cb(self, widget, event, activity):
+description = self._get_text_from_buffer()
+if 'description' in activity.metadata and \
+description == activity.metadata['description']:
+return
+
+activity.metadata['description'] = description
+activity.save()
+return False
+
+
 class ActivityToolbar(gtk.Toolbar):
 The Activity toolbar with the Journal entry title, sharing
and Stop buttons
@@ -261,6 +327,11 @@ class ActivityToolbar(gtk.Toolbar):
 self.insert(separator, -1)
 separator.show()
 
+if activity.metadata:
+description_item = DescriptionItem(activity)
+description_item.show()
+self.insert(description_item, -1)
+
 self.share = ShareButton(activity)
 self.share.show()
 self.insert(self.share, -1)
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH 2/2] Backport of Remove the Naming Alert in sugar-toolkit-gtk3

2012-04-19 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

With the new 'Write to Journal anytime' feature it is possible
to write a description within an activity. Hopefully this leads
to more usage of the Journal for reflection by the learner. The
hinting nature ('you have not named your session yet') of the
Naming Alert has not been replaced, though.

This feature is requested by teachers and will provide a more consistent
experience in sugar 0.96 between gtk2 and gtk3 activities.

The original patch is from Simon Schampijer si...@laptop.org

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 po/POTFILES.in|1 -
 src/sugar/activity/Makefile.am|1 -
 src/sugar/activity/activity.py|   18 +--
 src/sugar/activity/namingalert.py |  306 -
 4 files changed, 5 insertions(+), 321 deletions(-)
 delete mode 100644 src/sugar/activity/namingalert.py

diff --git a/po/POTFILES.in b/po/POTFILES.in
index c9a8443..f3c984e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,4 @@
 src/sugar/activity/activity.py
-src/sugar/activity/namingalert.py
 src/sugar/activity/widgets.py
 src/sugar/graphics/alert.py
 src/sugar/graphics/colorbutton.py
diff --git a/src/sugar/activity/Makefile.am b/src/sugar/activity/Makefile.am
index f3a663a..ca94b4d 100644
--- a/src/sugar/activity/Makefile.am
+++ b/src/sugar/activity/Makefile.am
@@ -7,5 +7,4 @@ sugar_PYTHON =  \
activityservice.py  \
bundlebuilder.py\
i18n.py \
-   namingalert.py  \
widgets.py
diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py
index 5844506..fdf9827 100644
--- a/src/sugar/activity/activity.py
+++ b/src/sugar/activity/activity.py
@@ -75,7 +75,6 @@ from sugar import util
 from sugar.presence import presenceservice
 from sugar.activity import i18n
 from sugar.activity.activityservice import ActivityService
-from sugar.activity.namingalert import NamingAlert
 from sugar.graphics import style
 from sugar.graphics.window import Window
 from sugar.graphics.alert import Alert
@@ -900,19 +899,12 @@ class Activity(Window, gtk.Container):
 
 self.emit('_closing')
 
-if skip_save or self._jobject is None or \
-self.metadata.get('title_set_by_user', '0') == '1':
-if not self._closing:
-if not self._prepare_close(skip_save):
-return
+if not self._closing:
+if not self._prepare_close(skip_save):
+return
 
-if not self._updating_jobject:
-self._complete_close()
-else:
-title_alert = NamingAlert(self, get_bundle_path())
-title_alert.set_transient_for(self.get_toplevel())
-title_alert.show()
-self.reveal()
+if not self._updating_jobject:
+self._complete_close()
 
 def __realize_cb(self, window):
 wm.set_bundle_id(window.window, self.get_bundle_id())
diff --git a/src/sugar/activity/namingalert.py 
b/src/sugar/activity/namingalert.py
deleted file mode 100644
index 078c27a..000
--- a/src/sugar/activity/namingalert.py
+++ /dev/null
@@ -1,306 +0,0 @@
-# Copyright (C) 2009 One Laptop Per Child
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-import gettext
-import os
-
-import gio
-import gtk
-import gobject
-import gconf
-
-from sugar.graphics import style
-from sugar.graphics.icon import Icon
-from sugar.graphics.xocolor import XoColor
-from sugar.graphics.icon import get_icon_file_name
-from sugar.graphics.toolbutton import ToolButton
-
-from sugar.bundle.activitybundle import ActivityBundle
-
-
-_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
-
-
-def _get_icon_name(metadata):
-file_name = None
-
-mime_type = metadata.get('mime_type', '')
-if not file_name and mime_type:
-icons = gio.content_type_get_icon(mime_type)
-for icon_name in icons.props.names:
-file_name = get_icon_file_name(icon_name)
-if file_name is not None:
-break
-
-if file_name is None or not os.path.exists(file_name):
-file_name = get_icon_file_name('application-octet-stream')
-
-return file_name
-
-
-class NamingToolbar(gtk.Toolbar):
- Toolbar 

[Sugar-devel] [PATCH] Avoid using a protected member in the filter of the favorites view -v2

2012-03-13 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Implement only a getter method to access the activity name.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/favoritesview.py |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/src/jarabe/desktop/favoritesview.py 
b/src/jarabe/desktop/favoritesview.py
index 5c76cdc..654f400 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -115,7 +115,7 @@ class FavoritesView(hippo.Canvas):
 query = query.strip()
 for icon in self._box.get_children():
 if icon not in [self._my_icon, self._current_activity]:
-activity_name = icon._activity_info.get_name().lower()
+activity_name = icon.get_activity_name().lower()
 if activity_name.find(query)  -1:
 icon.alpha = 1.0
 else:
@@ -508,6 +508,9 @@ class ActivityIcon(CanvasIcon):
 return self._activity_info.get_activity_version()
 version = property(get_version, None)
 
+def get_activity_name(self):
+return self._activity_info.get_name()
+
 def _get_installation_time(self):
 return self._activity_info.get_installation_time()
 installation_time = property(_get_installation_time, None)
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [Sugar] Only add a group of selections to the clipboard if there are anything available. -v2

2012-03-13 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This problem is affecting Text to Speech with Write activity,
because there are only a selection in the secondary clipboard
but a icon is displayed in the frame without anything selected.

v2: Addressed comments from Sasha, add a line and do patch with -U4 option

Signed-off-by: Gonzalo Odiard
---
 src/jarabe/frame/clipboardpanelwindow.py |   12 
 1 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/jarabe/frame/clipboardpanelwindow.py 
b/src/jarabe/frame/clipboardpanelwindow.py
index aefec7b..b73572e 100644
--- a/src/jarabe/frame/clipboardpanelwindow.py
+++ b/src/jarabe/frame/clipboardpanelwindow.py
@@ -55,23 +55,27 @@ class ClipboardPanelWindow(FrameWindow):
 if self._clipboard_tray.owns_clipboard():
 return
 
 cb_service = clipboard.get_instance()
-key = cb_service.add_object(name=)
-cb_service.set_object_percent(key, percent=0)
 
 targets = x_clipboard.wait_for_targets()
+cb_selections = []
 for target in targets:
 if target not in ('TIMESTAMP', 'TARGETS',
   'MULTIPLE', 'SAVE_TARGETS'):
 logging.debug('Asking for target %s.', target)
 selection = x_clipboard.wait_for_contents(target)
 if not selection:
 logging.warning('no data for selection target %s.', target)
 continue
-self._add_selection(key, selection)
+cb_selections.append(selection)
 
-cb_service.set_object_percent(key, percent=100)
+if len(cb_selections)  0:
+key = cb_service.add_object(name=)
+cb_service.set_object_percent(key, percent=0)
+for selection in cb_selections:
+self._add_selection(key, selection)
+cb_service.set_object_percent(key, percent=100)
 
 def _add_selection(self, key, selection):
 if not selection.data:
 logging.warning('no data for selection target %s.', selection.type)
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [Sugar] Show a clean error in log if not libraries needed to do tts - SL #3345

2012-03-09 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 extensions/deviceicon/speech.py |   11 +--
 extensions/globalkey/speech.py  |   21 +
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
index 6b8f915..b231f26 100644
--- a/extensions/deviceicon/speech.py
+++ b/extensions/deviceicon/speech.py
@@ -14,6 +14,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
+import logging
 from gettext import gettext as _
 
 import glib
@@ -29,8 +30,13 @@ from sugar.graphics.menuitem import MenuItem
 from sugar.graphics import style
 
 from jarabe.frame.frameinvoker import FrameWidgetInvoker
-from jarabe.model import speech
 
+tts_available = True
+try:
+from jarabe.model import speech
+except:
+logging.error('Text to speech no avalable: error loading dependencies')
+tts_available = False
 
 _ICON_NAME = 'microphone'
 
@@ -145,4 +151,5 @@ class SpeechPalette(Palette):
 
 
 def setup(tray):
-tray.add_device(SpeechDeviceView())
+if tts_available:
+tray.add_device(SpeechDeviceView())
diff --git a/extensions/globalkey/speech.py b/extensions/globalkey/speech.py
index 2879b69..d0dd55d 100644
--- a/extensions/globalkey/speech.py
+++ b/extensions/globalkey/speech.py
@@ -14,16 +14,21 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-from jarabe.model import speech
+tts_available = True
+try:
+from jarabe.model import speech
+except:
+tts_available = False
 
 BOUND_KEYS = ['altshifts']
 
 
 def handle_key_press(key):
-manager = speech.get_speech_manager()
-if manager.is_paused:
-manager.restart()
-elif not manager.is_playing:
-manager.say_selected_text()
-else:
-manager.pause()
+if tts_available:
+manager = speech.get_speech_manager()
+if manager.is_paused:
+manager.restart()
+elif not manager.is_playing:
+manager.say_selected_text()
+else:
+manager.pause()
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH sugar-toolkit-gtk3] Avoid stretching the preview image.

2012-02-13 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch apply over Do the preview in the activity using cairo intead of 
GdkPixbuf -v2

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/activity/activity.py |   15 ++-
 1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/src/sugar3/activity/activity.py b/src/sugar3/activity/activity.py
index 8c1200c..7b0693b 100644
--- a/src/sugar3/activity/activity.py
+++ b/src/sugar3/activity/activity.py
@@ -664,7 +664,20 @@ class Activity(Window, Gtk.Container):
 cairo_context = cairo.Context(preview_surface)
 preview_scale_w = preview_width * 1.0 / width
 preview_scale_h = preview_height * 1.0 / height
-cairo_context.scale(preview_scale_w, preview_scale_h)
+scale = min(preview_scale_w, preview_scale_h)
+
+margin_x = int((preview_width - (width * scale)) / 2)
+margin_y = int((preview_height - (height * scale)) / 2)
+
+cairo_context.rectangle(0, 0, preview_width, preview_height)
+cairo_context.set_source_rgb(1, 1, 1)
+cairo_context.fill()
+
+cairo_context.rectangle(margin_x, margin_y, preview_width,
+preview_height)
+cairo_context.clip()
+cairo_context.translate(margin_x, margin_y)
+cairo_context.scale(scale, scale)
 Gdk.cairo_set_source_window(cairo_context, window, -x, -y)
 cairo_context.paint()
 
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH StopWatch] Add mime type when save in the journal

2012-02-10 Thread godiard
From: Agustin Zubiaga a...@sugarlabs.org

This enable to other activities to identify the data

Signed-off-by: Agustin Zubiaga a...@sugarlabs.org
Reviewed-by: Gonzalo Odiard gonz...@laptop.org
---
 activity.py|1 +
 activity/activity.info |1 +
 activity/mimetypes.xml |7 +++
 3 files changed, 9 insertions(+), 0 deletions(-)
 create mode 100644 activity/mimetypes.xml

diff --git a/activity.py b/activity.py
index 88313e2..306b081 100644
--- a/activity.py
+++ b/activity.py
@@ -166,6 +166,7 @@ class StopWatchActivity(Activity):
 self.gui.set_all(q)
 
 def write_file(self, file_path):
+self.metadata['mime_type'] = 'application/x-stopwatch-activity'
 q = self.gui.get_all()
 f = open(file_path, 'w')
 cPickle.dump(q, f)
diff --git a/activity/activity.info b/activity/activity.info
index c8fd3da..5ccabfa 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -6,3 +6,4 @@ icon = activity-stopwatch
 activity_version = 13
 show_launcher = yes
 license = GPLv3+
+mime_types = application/x-stopwatch-activity;
diff --git a/activity/mimetypes.xml b/activity/mimetypes.xml
new file mode 100644
index 000..2426820
--- /dev/null
+++ b/activity/mimetypes.xml
@@ -0,0 +1,7 @@
+?xml version=1.0 encoding=UTF-8?
+mime-info xmlns=http://www.freedesktop.org/standards/shared-mime-info;
+  mime-type type=application/x-stopwatch-activity
+ comment xml:lang=enStopWatch Activity/comment
+ glob pattern=*.stopwatch/
+  /mime-type
+/mime-info
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Record] Use named parameters in gettext strings

2012-02-10 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

When there are more than one parameter with the same type
gettext need named parameters to enable the translators to change
the order if needed.
Pootle server complain about this format strings in Record activity,
and you can see the same error doing ./setup.py genpot

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 glive.py |3 ++-
 model.py |6 --
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/glive.py b/glive.py
index fd9a5af..413dc60 100644
--- a/glive.py
+++ b/glive.py
@@ -393,7 +393,8 @@ class Glive:
 stringType = constants.MEDIA_INFO[type]['istr']
 
 # Translators: photo by photographer, e.g. Photo by Mary
-tl[gst.TAG_TITLE] = _('%s by %s') % (stringType, 
self.model.get_nickname())
+tl[gst.TAG_TITLE] = _('%(type)s by %(name)s') % {'type': cstringType,
+'name': self.model.get_nickname()}
 return tl
 
 def blockedCb(self, x, y, z):
diff --git a/model.py b/model.py
index 884325b..d47671c 100644
--- a/model.py
+++ b/model.py
@@ -180,7 +180,8 @@ class Model:
 
 mins = value / 60
 secs = value % 60
-text = _('%d:%02d remaining') % (mins, secs)
+text = _('%(mins)d:%(secs)02d remaining') % {'mins': mins,
+'secs': secs}
 
 self.set_progress(progress_value, text)
 
@@ -381,7 +382,8 @@ class Model:
 stringType = constants.MEDIA_INFO[type]['istr']
 
 # Translators: photo by photographer, e.g. Photo by Mary
-recd.title = _('%s by %s') % (stringType, recd.recorderName)
+recd.title = _('%(type)s by %(name)s') % {'type': stringType,
+'name': recd.recorderName}
 
 color = sugar.profile.get_color()
 recd.colorStroke = color.get_stroke_color()
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH sugar-toolkit-gtk3] Do the preview in the activity using cairo intead of GdkPixbufa -v2

2012-02-10 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

---

v2: Create the image without the toolbar
---
 src/sugar3/activity/activity.py |   39 ---
 1 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/src/sugar3/activity/activity.py b/src/sugar3/activity/activity.py
index 19c1974..8c1200c 100644
--- a/src/sugar3/activity/activity.py
+++ b/src/sugar3/activity/activity.py
@@ -54,11 +54,12 @@ import os
 import time
 from hashlib import sha1
 from functools import partial
+import StringIO
 
 from gi.repository import GConf
 from gi.repository import Gtk
 from gi.repository import Gdk
-from gi.repository import GdkPixbuf
+import cairo
 from gi.repository import GObject
 import dbus
 import dbus.service
@@ -642,26 +643,34 @@ class Activity(Window, Gtk.Container):
 binary content of a png image with a width of 300 and a height of 225
 pixels.
 
-if self.canvas is None or not hasattr(self.canvas, 'get_snapshot'):
+if self.canvas is None or not hasattr(self.canvas, 'get_window'):
 return None
-pixmap = self.canvas.get_snapshot((-1, -1, 0, 0))
 
-width, height = pixmap.get_size()
-pixbuf = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, 0, 8, width, 
height)
-pixbuf = pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(),
-  0, 0, 0, 0, width, height)
-pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225),
- GdkPixbuf.InterpType.BILINEAR)
+window = self.canvas.get_window()
 
-preview_data = []
+x, y = 0, 0
+width, height = window.get_width(), window.get_height()
 
-def save_func(buf, data):
-data.append(buf)
+if not self.canvas.get_has_window():
+alloc = self.canvas.get_allocation()
+x, y = alloc.x, alloc.y
+width, height = alloc.width, alloc.height
 
-pixbuf.save_to_callback(save_func, 'png', user_data=preview_data)
-preview_data = ''.join(preview_data)
+preview_width, preview_height = style.zoom(300), style.zoom(225)
 
-return preview_data
+preview_surface = Gdk.Window.create_similar_surface(window,
+cairo.CONTENT_COLOR, preview_width, preview_height)
+
+cairo_context = cairo.Context(preview_surface)
+preview_scale_w = preview_width * 1.0 / width
+preview_scale_h = preview_height * 1.0 / height
+cairo_context.scale(preview_scale_w, preview_scale_h)
+Gdk.cairo_set_source_window(cairo_context, window, -x, -y)
+cairo_context.paint()
+
+preview_str = StringIO.StringIO()
+preview_surface.write_to_png(preview_str)
+return preview_str.getvalue()
 
 def _get_buddies(self):
 if self.shared_activity is not None:
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH sugar-toolkit-gtk3] Do the preview in the activity using cairo intead of GdkPixbuf

2012-02-09 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar3/activity/activity.py |   33 ++---
 1 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/src/sugar3/activity/activity.py b/src/sugar3/activity/activity.py
index 19c1974..e943d44 100644
--- a/src/sugar3/activity/activity.py
+++ b/src/sugar3/activity/activity.py
@@ -54,11 +54,12 @@ import os
 import time
 from hashlib import sha1
 from functools import partial
+import StringIO
 
 from gi.repository import GConf
 from gi.repository import Gtk
 from gi.repository import Gdk
-from gi.repository import GdkPixbuf
+import cairo
 from gi.repository import GObject
 import dbus
 import dbus.service
@@ -642,26 +643,28 @@ class Activity(Window, Gtk.Container):
 binary content of a png image with a width of 300 and a height of 225
 pixels.
 
-if self.canvas is None or not hasattr(self.canvas, 'get_snapshot'):
+if self.canvas is None or not hasattr(self.canvas, 'get_window'):
 return None
-pixmap = self.canvas.get_snapshot((-1, -1, 0, 0))
 
-width, height = pixmap.get_size()
-pixbuf = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, 0, 8, width, 
height)
-pixbuf = pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(),
-  0, 0, 0, 0, width, height)
-pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225),
- GdkPixbuf.InterpType.BILINEAR)
+window = self.canvas.get_window()
 
-preview_data = []
+width, height = window.get_width(), window.get_height()
 
-def save_func(buf, data):
-data.append(buf)
+preview_width, preview_height = style.zoom(300), style.zoom(225)
 
-pixbuf.save_to_callback(save_func, 'png', user_data=preview_data)
-preview_data = ''.join(preview_data)
+preview_surface = Gdk.Window.create_similar_surface(window,
+cairo.CONTENT_COLOR, preview_width, preview_height)
 
-return preview_data
+cairo_context = cairo.Context(preview_surface)
+preview_scale_w = preview_width * 1.0 / width
+preview_scale_h = preview_height * 1.0 / height
+cairo_context.scale(preview_scale_w, preview_scale_h)
+Gdk.cairo_set_source_window(cairo_context, window, 0, 0)
+cairo_context.paint()
+
+preview_str = StringIO.StringIO()
+preview_surface.write_to_png(preview_str)
+return preview_str.getvalue()
 
 def _get_buddies(self):
 if self.shared_activity is not None:
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Moon] Add date information to the information displayed - SL #2749

2012-02-08 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The patch set the locale to use calendar to get week days and mont days.

Signed-off-by: Flavio Danesse fdane...@gmail.com
Reviewed-by: Gonzalo Odiard gonz...@laptop.org
---
 moon.py |   19 ++-
 1 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/moon.py b/moon.py
index f9eca9d..bd4bd2b 100755
--- a/moon.py
+++ b/moon.py
@@ -36,7 +36,9 @@ from sugar.graphics.toggletoolbutton import ToggleToolButton
 from gettext import gettext as _
 import math
 import time
+import calendar
 import os
+import locale
 
 try:
 import json
@@ -67,6 +69,12 @@ class MoonActivity(activity.Activity):
 self._name = handle
 self.set_title(_(Moon))
 
+# Set the locale to format dates
+lang = os.getenv('LANG')
+if lang.find('.')  -1:
+lang = lang[:lang.find('.')]
+locale.setlocale(locale.LC_TIME, lang)
+
 # Defaults (Resume priority, persistent file secondary, fall-back 
hardcoded)
 if handle.object_id == None:
 print Launched from home.
@@ -242,12 +250,21 @@ class MoonActivity(activity.Activity):
 gobject.source_remove(self.update_moon_image_timeout)
 self.update_moon_image_view()
 
+def format_date(self, date_time):
+year = date_time.tm_year
+month = calendar.month_name[date_time.tm_mon - 1]
+day = date_time.tm_mday
+week_day = calendar.day_name[date_time.tm_wday - 1]
+return %(week_day)s, %(day)s %(month)s %(year)s % \
+{'week_day':week_day, 'day':day, 'month':month, 'year':year}
+
 def update_text_information_view(self):
 Generate Moon data and update text based information view.
 
 self.data_model.update_moon_calculations(time.time())
 information_string = 
-information_string += _(Today's Moon Information\n\n)
+information_string += _(Today's Moon Information\n)
+information_string += %s\n\n % self.format_date(time.localtime())
 information_string += _(Phase:\n%s\n\n) % 
(self.data_model.moon_phase_name(self.data_model.phase_of_moon))
 information_string += _(Julian Date:\n%.2f (astronomical)\n\n) % 
(self.data_model.julian_date)
 information_string += _(Age:\n%(days).0f days, %(hours).0f hours, 
%(minutes).0f minutes\n\n) % {'days':self.data_model.days_old, 
'hours':self.data_model.hours_old, 'minutes':self.data_model.minutes_old}
-- 
1.7.7.6

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Sugar] Implementation of Text to Speech in Sugar Feature - v4

2012-01-31 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch implement the text to speech feature using a
gstremer espeak plugin and using a device icon in the frame
to enable the user to configure parameters and play/pause/stop
the spoken text. The configuration is saved in gconf.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

--

* Use the standard MenuItem and removed SugarMenuItem.
* Return to altshifts shortcut. Pressing the shortcut again
while a text is being played pause the play, to mimic the play/pause button.
---
 data/sugar.schemas.in |   24 
 extensions/deviceicon/Makefile.am |1 +
 extensions/deviceicon/speech.py   |  148 
 extensions/globalkey/Makefile.am  |1 +
 extensions/globalkey/speech.py|   29 +
 src/jarabe/model/Makefile.am  |1 +
 src/jarabe/model/speech.py|  230 +
 src/jarabe/view/keyhandler.py |   29 +-
 8 files changed, 435 insertions(+), 28 deletions(-)
 create mode 100644 extensions/deviceicon/speech.py
 create mode 100644 extensions/globalkey/speech.py
 create mode 100644 src/jarabe/model/speech.py

diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in
index aaef381..226b41f 100644
--- a/data/sugar.schemas.in
+++ b/data/sugar.schemas.in
@@ -368,5 +368,29 @@
   /locale
 /schema
 
+schema
+  key/schemas/desktop/sugar/speech/pitch/key
+  applyto/desktop/sugar/speech/pitch/applyto
+  ownersugar/owner
+  typeint/type
+  default0/default
+  locale name=C
+shortPitch value for the speech sugar service/short
+longPitch value used by the speech service in Sugar/long
+  /locale
+/schema
+
+schema
+  key/schemas/desktop/sugar/speech/rate/key
+  applyto/desktop/sugar/speech/rate/applyto
+  ownersugar/owner
+  typeint/type
+  default0/default
+  locale name=C
+shortRate value for the speech sugar service/short
+longRate value used by the speech service in Sugar/long
+  /locale
+/schema
+
   /schemalist
 /gconfschemafile
diff --git a/extensions/deviceicon/Makefile.am 
b/extensions/deviceicon/Makefile.am
index 118d866..7ed1f77 100644
--- a/extensions/deviceicon/Makefile.am
+++ b/extensions/deviceicon/Makefile.am
@@ -5,5 +5,6 @@ sugar_PYTHON =  \
battery.py  \
network.py  \
speaker.py  \
+   speech.py   \
touchpad.py \
volume.py
diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
new file mode 100644
index 000..6b8f915
--- /dev/null
+++ b/extensions/deviceicon/speech.py
@@ -0,0 +1,148 @@
+# Copyright (C) 2011 One Laptop Per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from gettext import gettext as _
+
+import glib
+import gtk
+import gconf
+import gobject
+
+from sugar.graphics.icon import Icon
+from sugar.graphics.tray import TrayIcon
+from sugar.graphics.palette import Palette
+from sugar.graphics.xocolor import XoColor
+from sugar.graphics.menuitem import MenuItem
+from sugar.graphics import style
+
+from jarabe.frame.frameinvoker import FrameWidgetInvoker
+from jarabe.model import speech
+
+
+_ICON_NAME = 'microphone'
+
+
+class SpeechDeviceView(TrayIcon):
+
+FRAME_POSITION_RELATIVE = 150
+
+def __init__(self):
+client = gconf.client_get_default()
+self._color = XoColor(client.get_string('/desktop/sugar/user/color'))
+TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color)
+self.set_palette_invoker(FrameWidgetInvoker(self))
+self._manager = speech.get_speech_manager()
+self._icon_widget.connect('button-release-event',
+  self.__button_release_event_cb)
+
+def create_palette(self):
+label = glib.markup_escape_text(_('Speech'))
+palette = SpeechPalette(label, manager=self._manager)
+palette.set_group_id('frame')
+return palette
+
+def __button_release_event_cb(self, widget, event):
+self.palette_invoker.notify_right_click()
+return True
+
+
+class SpeechPalette(Palette):
+
+def __init__(self, primary_text, manager):
+Palette.__init__(self, label=primary_text)
+
+self._manager = manager
+self._manager.connect('play', 

[Sugar-devel] [PATCH Sugar] Implementation of Text to Speech in Sugar Feature - v5

2012-01-31 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch implement the text to speech feature using the
gstremer espeak plugin and using a device icon in the frame
to enable the user to configure parameters and play/pause/stop
the spoken text. The configuration is saved in gconf.
gstreamer-plugins-espeak is in use in many activities, 
but is added now as a dependency to Sugar.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

--

* Use the standard MenuItem and removed SugarMenuItem.
* Return to altshifts shortcut. Pressing the shortcut again
while a text is being played pause the play, to mimic the play/pause button.
---
 data/sugar.schemas.in |   24 
 extensions/deviceicon/Makefile.am |1 +
 extensions/deviceicon/speech.py   |  148 
 extensions/globalkey/Makefile.am  |1 +
 extensions/globalkey/speech.py|   29 +
 src/jarabe/model/Makefile.am  |1 +
 src/jarabe/model/speech.py|  230 +
 src/jarabe/view/keyhandler.py |   29 +-
 8 files changed, 435 insertions(+), 28 deletions(-)
 create mode 100644 extensions/deviceicon/speech.py
 create mode 100644 extensions/globalkey/speech.py
 create mode 100644 src/jarabe/model/speech.py

diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in
index aaef381..226b41f 100644
--- a/data/sugar.schemas.in
+++ b/data/sugar.schemas.in
@@ -368,5 +368,29 @@
   /locale
 /schema
 
+schema
+  key/schemas/desktop/sugar/speech/pitch/key
+  applyto/desktop/sugar/speech/pitch/applyto
+  ownersugar/owner
+  typeint/type
+  default0/default
+  locale name=C
+shortPitch value for the speech sugar service/short
+longPitch value used by the speech service in Sugar/long
+  /locale
+/schema
+
+schema
+  key/schemas/desktop/sugar/speech/rate/key
+  applyto/desktop/sugar/speech/rate/applyto
+  ownersugar/owner
+  typeint/type
+  default0/default
+  locale name=C
+shortRate value for the speech sugar service/short
+longRate value used by the speech service in Sugar/long
+  /locale
+/schema
+
   /schemalist
 /gconfschemafile
diff --git a/extensions/deviceicon/Makefile.am 
b/extensions/deviceicon/Makefile.am
index 118d866..7ed1f77 100644
--- a/extensions/deviceicon/Makefile.am
+++ b/extensions/deviceicon/Makefile.am
@@ -5,5 +5,6 @@ sugar_PYTHON =  \
battery.py  \
network.py  \
speaker.py  \
+   speech.py   \
touchpad.py \
volume.py
diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
new file mode 100644
index 000..6b8f915
--- /dev/null
+++ b/extensions/deviceicon/speech.py
@@ -0,0 +1,148 @@
+# Copyright (C) 2011 One Laptop Per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from gettext import gettext as _
+
+import glib
+import gtk
+import gconf
+import gobject
+
+from sugar.graphics.icon import Icon
+from sugar.graphics.tray import TrayIcon
+from sugar.graphics.palette import Palette
+from sugar.graphics.xocolor import XoColor
+from sugar.graphics.menuitem import MenuItem
+from sugar.graphics import style
+
+from jarabe.frame.frameinvoker import FrameWidgetInvoker
+from jarabe.model import speech
+
+
+_ICON_NAME = 'microphone'
+
+
+class SpeechDeviceView(TrayIcon):
+
+FRAME_POSITION_RELATIVE = 150
+
+def __init__(self):
+client = gconf.client_get_default()
+self._color = XoColor(client.get_string('/desktop/sugar/user/color'))
+TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color)
+self.set_palette_invoker(FrameWidgetInvoker(self))
+self._manager = speech.get_speech_manager()
+self._icon_widget.connect('button-release-event',
+  self.__button_release_event_cb)
+
+def create_palette(self):
+label = glib.markup_escape_text(_('Speech'))
+palette = SpeechPalette(label, manager=self._manager)
+palette.set_group_id('frame')
+return palette
+
+def __button_release_event_cb(self, widget, event):
+self.palette_invoker.notify_right_click()
+return True
+
+
+class SpeechPalette(Palette):
+
+def __init__(self, primary_text, manager):
+

[Sugar-devel] [Sugar 1/2] Only add a group of selections to the clipboard if there are anything available.

2012-01-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This problem is affecting Text to Speech with Write activity,
because there are only a selection in the secondary clipboard
but a icon is displayed in the frame without anything selected.

Signed-off-by: Gonzalo Odiard
---
 src/jarabe/frame/clipboardpanelwindow.py |   11 +++
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/jarabe/frame/clipboardpanelwindow.py 
b/src/jarabe/frame/clipboardpanelwindow.py
index aefec7b..209c508 100644
--- a/src/jarabe/frame/clipboardpanelwindow.py
+++ b/src/jarabe/frame/clipboardpanelwindow.py
@@ -56,10 +56,9 @@ class ClipboardPanelWindow(FrameWindow):
 return
 
 cb_service = clipboard.get_instance()
-key = cb_service.add_object(name=)
-cb_service.set_object_percent(key, percent=0)
 
 targets = x_clipboard.wait_for_targets()
+cb_selections = []
 for target in targets:
 if target not in ('TIMESTAMP', 'TARGETS',
   'MULTIPLE', 'SAVE_TARGETS'):
@@ -68,9 +67,13 @@ class ClipboardPanelWindow(FrameWindow):
 if not selection:
 logging.warning('no data for selection target %s.', target)
 continue
+cb_selections.append(selection)
+if len(cb_selections)  0:
+key = cb_service.add_object(name=)
+cb_service.set_object_percent(key, percent=0)
+for selection in cb_selections:
 self._add_selection(key, selection)
-
-cb_service.set_object_percent(key, percent=100)
+cb_service.set_object_percent(key, percent=100)
 
 def _add_selection(self, key, selection):
 if not selection.data:
-- 
1.7.7.5

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [Sugar 2/2] Implementation of Text to Speech in Sugar Feature - v3

2012-01-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Changes:

* Fixes in schema descriptions.
* Frame position value.
* UI fixes according to different reviews.
* Use a SugarMenuItem to mimic MenuItem behaviour because in the gtk3
palettes can coexist menues and other widgets. This is not mandatory now
but will do easier migration.
* Fixed max/min values in configurations. I was using values from espeak
documentation but should use from gst-plugins-espeak

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 data/sugar.schemas.in |   24 
 extensions/deviceicon/Makefile.am |1 +
 extensions/deviceicon/speech.py   |  230 
 extensions/globalkey/Makefile.am  |1 +
 extensions/globalkey/speech.py|   23 
 src/jarabe/model/Makefile.am  |1 +
 src/jarabe/model/speech.py|  235 +
 src/jarabe/view/keyhandler.py |   29 +-
 8 files changed, 516 insertions(+), 28 deletions(-)
 create mode 100644 extensions/deviceicon/speech.py
 create mode 100644 extensions/globalkey/speech.py
 create mode 100644 src/jarabe/model/speech.py

diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in
index aaef381..226b41f 100644
--- a/data/sugar.schemas.in
+++ b/data/sugar.schemas.in
@@ -368,5 +368,29 @@
   /locale
 /schema
 
+schema
+  key/schemas/desktop/sugar/speech/pitch/key
+  applyto/desktop/sugar/speech/pitch/applyto
+  ownersugar/owner
+  typeint/type
+  default0/default
+  locale name=C
+shortPitch value for the speech sugar service/short
+longPitch value used by the speech service in Sugar/long
+  /locale
+/schema
+
+schema
+  key/schemas/desktop/sugar/speech/rate/key
+  applyto/desktop/sugar/speech/rate/applyto
+  ownersugar/owner
+  typeint/type
+  default0/default
+  locale name=C
+shortRate value for the speech sugar service/short
+longRate value used by the speech service in Sugar/long
+  /locale
+/schema
+
   /schemalist
 /gconfschemafile
diff --git a/extensions/deviceicon/Makefile.am 
b/extensions/deviceicon/Makefile.am
index 118d866..7ed1f77 100644
--- a/extensions/deviceicon/Makefile.am
+++ b/extensions/deviceicon/Makefile.am
@@ -5,5 +5,6 @@ sugar_PYTHON =  \
battery.py  \
network.py  \
speaker.py  \
+   speech.py   \
touchpad.py \
volume.py
diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
new file mode 100644
index 000..6311fd6
--- /dev/null
+++ b/extensions/deviceicon/speech.py
@@ -0,0 +1,230 @@
+# Copyright (C) 2011 One Laptop Per Child
+# Copyright (C) 2011 Gonzalo Odiard
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from gettext import gettext as _
+
+import glib
+import gtk
+import gconf
+import gobject
+
+from sugar.graphics.icon import Icon
+from sugar.graphics.tray import TrayIcon
+from sugar.graphics.palette import Palette
+from sugar.graphics.xocolor import XoColor
+from sugar.graphics import style
+
+from jarabe.frame.frameinvoker import FrameWidgetInvoker
+from jarabe.model import speech
+
+
+_ICON_NAME = 'microphone'
+
+
+class SpeechDeviceView(TrayIcon):
+
+FRAME_POSITION_RELATIVE = 150
+
+def __init__(self):
+client = gconf.client_get_default()
+self._color = XoColor(client.get_string('/desktop/sugar/user/color'))
+TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color)
+self.set_palette_invoker(FrameWidgetInvoker(self))
+self._manager = speech.get_speech_manager()
+self._icon_widget.connect('button-release-event',
+  self.__button_release_event_cb)
+
+def create_palette(self):
+label = glib.markup_escape_text(_('Speech'))
+palette = SpeechPalette(label, manager=self._manager)
+palette.set_group_id('frame')
+return palette
+
+def __button_release_event_cb(self, widget, event):
+self.palette_invoker.notify_right_click()
+return True
+
+
+class SugarMenuItem(gtk.EventBox):
+
+__gsignals__ = {
+'clicked': (gobject.SIGNAL_RUN_FIRST, None, [])
+}
+
+def __init__(self, icon_name, label_text):
+gtk.EventBox.__init__(self)
+

[Sugar-devel] [Sugar] Implement text to speech in Sugar feature - v2

2012-01-17 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Added controls to pause/stop and addressed suggestions
in the review process.
---
 data/sugar.schemas.in |   28 
 extensions/deviceicon/Makefile.am |1 +
 extensions/deviceicon/speech.py   |  204 
 extensions/globalkey/Makefile.am  |1 +
 extensions/globalkey/speech.py|   24 
 src/jarabe/model/Makefile.am  |1 +
 src/jarabe/model/speech.py|  266 +
 src/jarabe/view/keyhandler.py |   29 +
 8 files changed, 526 insertions(+), 28 deletions(-)
 create mode 100644 extensions/deviceicon/speech.py
 create mode 100644 extensions/globalkey/speech.py
 create mode 100644 src/jarabe/model/speech.py

diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in
index 8b3e1ad..66d3391 100644
--- a/data/sugar.schemas.in
+++ b/data/sugar.schemas.in
@@ -368,5 +368,33 @@
   /locale
 /schema
 
+schema
+  key/schemas/desktop/sugar/speech/pitch/key
+  applyto/desktop/sugar/speech/pitch/applyto
+  ownersugar/owner
+  typeint/type
+  default50/default
+  locale name=C
+shortDefault pitch to the speech sugar service/short
+longPitch value used by the speech service in Sugar,
+can be changed by the user, with controls in a icon
+in the frame/long
+  /locale
+/schema
+
+schema
+  key/schemas/desktop/sugar/speech/rate/key
+  applyto/desktop/sugar/speech/rate/applyto
+  ownersugar/owner
+  typeint/type
+  default170/default
+  locale name=C
+shortDefault rate to the speech sugar service/short
+longRate value used by the speech service in Sugar,
+can be changed by the user, with controls in a icon
+in the frame/long
+  /locale
+/schema
+
   /schemalist
 /gconfschemafile
diff --git a/extensions/deviceicon/Makefile.am 
b/extensions/deviceicon/Makefile.am
index 118d866..7ed1f77 100644
--- a/extensions/deviceicon/Makefile.am
+++ b/extensions/deviceicon/Makefile.am
@@ -5,5 +5,6 @@ sugar_PYTHON =  \
battery.py  \
network.py  \
speaker.py  \
+   speech.py   \
touchpad.py \
volume.py
diff --git a/extensions/deviceicon/speech.py b/extensions/deviceicon/speech.py
new file mode 100644
index 000..4528e98
--- /dev/null
+++ b/extensions/deviceicon/speech.py
@@ -0,0 +1,204 @@
+# Copyright (C) 2011 One Laptop Per Child
+# Copyright (C) 2011 Gonzalo Odiard
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from gettext import gettext as _
+import gconf
+
+import glib
+import gtk
+
+from sugar.graphics.icon import Icon
+from sugar.graphics.menuitem import MenuItem
+from sugar.graphics.tray import TrayIcon
+from sugar.graphics.palette import Palette
+from sugar.graphics.xocolor import XoColor
+from sugar.graphics.toolbutton import ToolButton
+
+from jarabe.frame.frameinvoker import FrameWidgetInvoker
+from jarabe.model import speech
+
+
+_ICON_NAME = 'microphone'
+
+
+class SpeechDeviceView(TrayIcon):
+
+FRAME_POSITION_RELATIVE = 105
+
+def __init__(self):
+client = gconf.client_get_default()
+self._color = XoColor(client.get_string('/desktop/sugar/user/color'))
+
+TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color)
+
+self.set_palette_invoker(FrameWidgetInvoker(self))
+
+self._manager = speech.get_speech_manager()
+
+self.connect('expose-event', self.__expose_event_cb)
+
+self._icon_widget.connect('button-release-event',
+  self.__button_release_event_cb)
+
+def create_palette(self):
+label = glib.markup_escape_text(_('Speech'))
+palette = SpeechPalette(label, manager=self._manager)
+palette.set_group_id('frame')
+return palette
+
+def __button_release_event_cb(self, widget, event):
+if event.button != 1:
+return False
+
+self.palette_invoker.notify_right_click()
+return True
+
+def __expose_event_cb(self, *args):
+self._update_info()
+
+
+class SpeechPalette(Palette):
+
+def __init__(self, primary_text, manager):
+Palette.__init__(self, label=primary_text)
+
+
+
+self._manager = manager
+

[Sugar-devel] [ImageViewer] Changes in the toolbar according to design team review

2012-01-12 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Change order in the full screen button, and icons in rotate buttons.

Signed-off-by: Agustin Zubiaga aguzubiag...@gmail.com
Reviewed-by: Gonzalo Odiard gonz...@laptop.org
---
 ImageViewerActivity.py |   22 
 icons/object-rotate-left.svg   |   16 +
 icons/object-rotate-right.svg  |   15 
 icons/rotate_anticlockwise.svg |   71 
 icons/rotate_clockwise.svg |   71 
 5 files changed, 39 insertions(+), 156 deletions(-)
 create mode 100644 icons/object-rotate-left.svg
 create mode 100644 icons/object-rotate-right.svg
 delete mode 100644 icons/rotate_anticlockwise.svg
 delete mode 100644 icons/rotate_clockwise.svg

diff --git a/ImageViewerActivity.py b/ImageViewerActivity.py
index 9bb06e5..e87ffc0 100644
--- a/ImageViewerActivity.py
+++ b/ImageViewerActivity.py
@@ -193,35 +193,29 @@ class ImageViewerActivity(activity.Activity):
 toolbar_box.toolbar.insert(zoom_original_button, -1)
 zoom_original_button.show()
 
+fullscreen_button = ToolButton('view-fullscreen')
+fullscreen_button.set_tooltip(_('Fullscreen'))
+fullscreen_button.connect('clicked', self.__fullscreen_cb)
+toolbar_box.toolbar.insert(fullscreen_button, -1)
+fullscreen_button.show()
+
 spacer = gtk.SeparatorToolItem()
-spacer.props.draw = False
 toolbar_box.toolbar.insert(spacer, -1)
 spacer.show()
 
-rotate_anticlockwise_button = ToolButton('rotate_anticlockwise')
+rotate_anticlockwise_button = ToolButton('object-rotate-left')
 rotate_anticlockwise_button.set_tooltip(_('Rotate anticlockwise'))
 rotate_anticlockwise_button.connect('clicked',
 self.__rotate_anticlockwise_cb)
 toolbar_box.toolbar.insert(rotate_anticlockwise_button, -1)
 rotate_anticlockwise_button.show()
 
-rotate_clockwise_button = ToolButton('rotate_clockwise')
+rotate_clockwise_button = ToolButton('object-rotate-right')
 rotate_clockwise_button.set_tooltip(_('Rotate clockwise'))
 rotate_clockwise_button.connect('clicked', self.__rotate_clockwise_cb)
 toolbar_box.toolbar.insert(rotate_clockwise_button, -1)
 rotate_clockwise_button.show()
 
-spacer = gtk.SeparatorToolItem()
-spacer.props.draw = False
-toolbar_box.toolbar.insert(spacer, -1)
-spacer.show()
-
-fullscreen_button = ToolButton('view-fullscreen')
-fullscreen_button.set_tooltip(_('Fullscreen'))
-fullscreen_button.connect('clicked', self.__fullscreen_cb)
-toolbar_box.toolbar.insert(fullscreen_button, -1)
-fullscreen_button.show()
-
 separator = gtk.SeparatorToolItem()
 separator.props.draw = False
 separator.set_expand(True)
diff --git a/icons/object-rotate-left.svg b/icons/object-rotate-left.svg
new file mode 100644
index 000..5dfa334
--- /dev/null
+++ b/icons/object-rotate-left.svg
@@ -0,0 +1,16 @@
+?xml version=1.0 encoding=utf-8?
+!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 
6.00 Build 14948)  --
+!DOCTYPE svg PUBLIC -//W3C//DTD SVG 1.1//EN 
http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd;
+svg version=1.1 xmlns=http://www.w3.org/2000/svg; 
xmlns:xlink=http://www.w3.org/1999/xlink; x=0px y=0px width=55px
+height=55px viewBox=0 0 55 55 enable-background=new 0 0 55 55 
xml:space=preserve
+
+g id=Rotate_Left__x28_90_xBA__CCW_x29_ 
+   g display=inline
+   polygon fill=#FF stroke=#FF 
stroke-linejoin=round points=12.183,32.074 7.513,23.012 21.07,27.354/  
   
+   path fill=none stroke=#FF stroke-width=3.5 
stroke-linecap=round d=M13.95,28.242
+   
c0-7.416,6.01-13.426,13.426-13.426s13.427,6.011,13.427,13.426c0,7.416-6.011,13.427-13.427,13.427
+   c-2.4,0-4.654-0.63-6.604-1.733/
+   /g
+/g
+
+/svg
diff --git a/icons/object-rotate-right.svg b/icons/object-rotate-right.svg
new file mode 100644
index 000..84c1638
--- /dev/null
+++ b/icons/object-rotate-right.svg
@@ -0,0 +1,15 @@
+?xml version=1.0 encoding=utf-8?
+!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 
6.00 Build 14948)  --
+!DOCTYPE svg PUBLIC -//W3C//DTD SVG 1.1//EN 
http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd;
+svg version=1.1 xmlns=http://www.w3.org/2000/svg; 
xmlns:xlink=http://www.w3.org/1999/xlink; x=0px y=0px width=55px
+height=55px viewBox=0 0 55 55 enable-background=new 0 0 55 55 
xml:space=preserve
+
+g id=Rotate_Right__x28_90_xBA__CW_x29_ 
+   polygon display=inline fill=#FF stroke=#FF 
stroke-linejoin=round points=42.693,31.332 47.363,22.27 
+   33.806,26.611   /
+   path display=inline fill=none stroke=#FF stroke-width=3.5 
stroke-linecap=round d=M40.926,27.5
+   

[Sugar-devel] [Chat] Enable palette over urls

2012-01-12 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch solves the problems pointed by Aleksey in the last patch,
disable the standard menu in the textview, reorganize the event_after method
and stop the mouse_slow detector when the palette popup.

Signed-by: Gonzalo Odiard gonz...@laptop.org
---
 chat/box.py |   26 +++---
 1 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/chat/box.py b/chat/box.py
index bfc8156..e82e19a 100644
--- a/chat/box.py
+++ b/chat/box.py
@@ -72,23 +72,20 @@ class TextBox(gtk.TextView):
 self._mouse_detector.connect('motion-slow', self._mouse_slow_cb)
 self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color())
 self.connect(event-after, self.event_after)
+self.connect('button-press-event', self.__button_press_cb)
 self.motion_notify_id = self.connect(motion-notify-event, \
 self.motion_notify_event)
 self.connect(visibility-notify-event, self.visibility_notify_event)
 
+def __button_press_cb(self, widget, event):
+if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
+# To disable the standard textview popup
+return True
+
 # Links can be activated by clicking.
 def event_after(self, widget, event):
 if event.type != gtk.gdk.BUTTON_RELEASE:
 return False
-if event.button == 2:
-# XXX `tag` is not defined
-#palette = tag.get_data('palette')
-#xw, yw = self.get_toplevel().get_pointer()
-#logging.debug('Popop palette by secondary button click')
-#palette.move(event.x, event.y)
-#palette.popup()
-#return False
-pass
 
 x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
 int(event.x), int(event.y))
@@ -97,7 +94,14 @@ class TextBox(gtk.TextView):
 for tag in iter_tags.get_tags():
 url = tag.get_data('url')
 if url is not None:
-self._show_via_journal(url)
+if event.button == 3:
+palette = tag.get_data('palette')
+xw, yw = self.get_toplevel().get_pointer()
+palette.move(int(xw), int(yw))
+palette.popup()
+else:
+self._show_via_journal(url)
+break
 
 return False
 
@@ -158,9 +162,9 @@ class TextBox(gtk.TextView):
 if hovering_over_link:
 if self.palette is not None:
 xw, yw = self.get_toplevel().get_pointer()
-logging.debug('move palette to %d %d', xw, yw)
 self.palette.move(xw, yw)
 self.palette.popup()
+self._mouse_detector.stop()
 else:
 if self.palette is not None:
 self.palette.popdown()
-- 
1.7.7.5

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [Infoslicer] Fix image downloading. If is downloading from upload.wikimedia.org don't add the page source url

2012-01-06 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 net.py |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/net.py b/net.py
index 98589f1..e3a13cf 100644
--- a/net.py
+++ b/net.py
@@ -82,7 +82,9 @@ def image_handler(root, uid, document):
 image_title = path.rsplit(/, 1)[-1]
 # attempt to fix incomplete paths
 if (not path.startswith(http://;)) and document.source != None 
and document.source.has_key(href):
-if path.startswith(/):
+if path.startswith(//upload):
+path = 'http:' + path
+elif path.startswith(/):
 path = document.source['href'].rsplit(/, 1)[0] + path
 else:
 path = document.source['href'].rsplit(/, 1)[0] + / + 
path
-- 
1.7.7.5

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [Chat 1/2] Remove use of hippo (1)

2012-01-05 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch remove the use of CanvasBox containers but does not
support smiles and the links are managed by the standard gtk procedure.
Smiles and links will be implemented in the next patch.

Signed-by-off: Gonzalo Odiard gonz...@laptop.org
---
 activity.py  |5 +-
 chat/box.py  |  174 +-
 chat/roundbox.py |   96 ++
 3 files changed, 190 insertions(+), 85 deletions(-)
 create mode 100644 chat/roundbox.py

diff --git a/activity.py b/activity.py
index 7d239cc..18ce996 100644
--- a/activity.py
+++ b/activity.py
@@ -14,7 +14,6 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-import hippo
 import gtk
 import logging
 import cjson
@@ -267,14 +266,12 @@ class Chat(activity.Activity):
 self.entry = entry
 
 self.chatbox = ChatBox()
-canvas = hippo.Canvas()
-canvas.set_root(self.chatbox)
 
 hbox = gtk.HBox()
 hbox.add(entry)
 
 box = gtk.VBox(homogeneous=False)
-box.pack_start(canvas)
+box.pack_start(self.chatbox)
 box.pack_start(hbox, expand=False)
 
 return box
diff --git a/chat/box.py b/chat/box.py
index a05015c..c3db97d 100644
--- a/chat/box.py
+++ b/chat/box.py
@@ -25,13 +25,11 @@ from gettext import gettext as _
 from os.path import join
 
 import gtk
-import hippo
 import pango
 import cairo
 
 from sugar.graphics import style
-from sugar.graphics.roundbox import CanvasRoundBox
-from sugar.graphics.palette import Palette, CanvasInvoker
+from sugar.graphics.palette import Palette
 from sugar.presence import presenceservice
 from sugar.graphics.menuitem import MenuItem
 from sugar.activity.activity import get_activity_root, show_object_in_journal
@@ -40,6 +38,7 @@ from sugar.datastore import datastore
 from sugar import profile
 
 from chat import smilies
+from chat.roundbox import RoundBox
 
 
 _URL_REGEXP = re.compile('((http|ftp)s?://)?'
@@ -47,10 +46,33 @@ _URL_REGEXP = re.compile('((http|ftp)s?://)?'
 '(:[1-9][0-9]{0,4})?(/[-a-zA-Z0-9/%~@_+=;:,.?#]*[a-zA-Z0-9/])?')
 
 
-class ChatBox(hippo.CanvasScrollbars):
+class ColorLabel(gtk.Label):
+
+def __init__(self, text, color=None):
+self._color = color
+if self._color is not None:
+text = 'span foreground=%s' % self._color.get_html() + \
+text + '/span'
+gtk.Label.__init__(self)
+self.set_use_markup(True)
+self.set_markup(text)
+
+
+class LinkLabel(ColorLabel):
+
+def __init__(self, text, color=None):
+self.text = 'a href=%s' % text + \
+text + '/a'
+ColorLabel.__init__(self, self.text, color)
+
+def create_palette(self):
+return _URLMenu(self.text)
+
+
+class ChatBox(gtk.ScrolledWindow):
 
 def __init__(self):
-hippo.CanvasScrollbars.__init__(self)
+gtk.ScrolledWindow.__init__(self)
 
 self.owner = presenceservice.get_instance().get_owner()
 
@@ -62,16 +84,16 @@ class ChatBox(hippo.CanvasScrollbars):
 self._last_msg = None
 self._chat_log = ''
 
-self._conversation = hippo.CanvasBox(
-spacing=0,
-box_width=-1,  # natural width
-background_color=style.COLOR_WHITE.get_int())
+self._conversation = gtk.VBox()
+self._conversation.set_homogeneous(False)
+#self._conversation.background_color=style.COLOR_WHITE
+#spacing=0,
+#box_width=-1,  # natural width
+#background_color=style.COLOR_WHITE.get_int())
 
-self.set_policy(hippo.ORIENTATION_HORIZONTAL,
-hippo.SCROLLBAR_NEVER)
-self.set_root(self._conversation)
-
-vadj = self.props.widget.get_vadjustment()
+self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+self.add_with_viewport(self._conversation)
+vadj = self.get_vadjustment()
 vadj.connect('changed', self._scroll_changed_cb)
 vadj.connect('value-changed', self._scroll_value_changed_cb)
 
@@ -89,7 +111,6 @@ class ChatBox(hippo.CanvasScrollbars):
 False: show what buddy said
 True: show what buddy did
 
-hippo layout:
 .- rb ---.
 | +name_vbox+ +msg_vbox+ |
 | | | || |
@@ -102,7 +123,6 @@ class ChatBox(hippo.CanvasScrollbars):
 | | ++ | |
 | ++ |
 `'
-###Warning hippocanvas dependency###
 
 if not buddy:
 buddy = self.owner
@@ -123,13 +143,13 @@ class ChatBox(hippo.CanvasScrollbars):
 color_fill_rgba = style.Color(color_fill_html).get_rgba()
 color_fill_gray = (color_fill_rgba[0] + color_fill_rgba[1] +

[Sugar-devel] [Chat 2/2] Use a textview to display messages - v2

2012-01-05 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The textview is used to display text, smilies and url.
The palette for the url use MouseSpeedDetector to have
the standard behaviour.

This patch is v2 and solve issues in the previous patch
and should be appiled after Remove use of hippo (1)

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 chat/box.py |  315 +--
 chat/smilies.py |   39 ++--
 2 files changed, 199 insertions(+), 155 deletions(-)

diff --git a/chat/box.py b/chat/box.py
index c3db97d..77f2bf5 100644
--- a/chat/box.py
+++ b/chat/box.py
@@ -26,10 +26,10 @@ from os.path import join
 
 import gtk
 import pango
-import cairo
+from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT
 
 from sugar.graphics import style
-from sugar.graphics.palette import Palette
+from sugar.graphics.palette import Palette, MouseSpeedDetector
 from sugar.presence import presenceservice
 from sugar.graphics.menuitem import MenuItem
 from sugar.activity.activity import get_activity_root, show_object_in_journal
@@ -46,6 +46,174 @@ _URL_REGEXP = re.compile('((http|ftp)s?://)?'
 '(:[1-9][0-9]{0,4})?(/[-a-zA-Z0-9/%~@_+=;:,.?#]*[a-zA-Z0-9/])?')
 
 
+class TextBox(gtk.TextView):
+
+__gsignals__ = {
+'mouse-enter': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+'mouse-leave': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+'right-click': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+}
+
+hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
+
+def __init__(self, color, bg_color, lang_rtl):
+self._lang_rtl = lang_rtl
+gtk.TextView.__init__(self)
+self.set_editable(False)
+self.set_cursor_visible(False)
+self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
+self.get_buffer().set_text(, 0)
+self.iter_text = self.get_buffer().get_iter_at_offset(0)
+self.fg_tag = self.get_buffer().create_tag(foreground_color,
+foreground=color.get_html())
+self._empty = True
+self.palette = None
+self._mouse_detector = MouseSpeedDetector(self, 200, 5)
+self._mouse_detector.connect('motion-slow', self._mouse_slow_cb)
+self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color())
+self.connect(event-after, self.event_after)
+self.motion_notify_id = self.connect(motion-notify-event, \
+self.motion_notify_event)
+self.connect(visibility-notify-event, self.visibility_notify_event)
+
+# Links can be activated by clicking.
+def event_after(self, widget, event):
+if event.type != gtk.gdk.BUTTON_RELEASE:
+return False
+if event.button == 2:
+palette = tag.get_data('palette')
+#xw, yw = self.get_toplevel().get_pointer()
+logging.error('Popop palette by secondary button click')
+palette.move(event.x, event.y)
+palette.popup()
+return False
+
+x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
+int(event.x), int(event.y))
+iter_tags = self.get_iter_at_location(x, y)
+
+for tag in iter_tags.get_tags():
+url = tag.get_data('url')
+if url is not None:
+self._show_via_journal(url)
+
+return False
+
+def _show_via_journal(self, url):
+Ask the journal to display a URL
+logging.debug('Create journal entry for URL: %s', url)
+jobject = datastore.create()
+metadata = {
+'title': %s: %s % (_('URL from Chat'), url),
+'title_set_by_user': '1',
+'icon-color': profile.get_color().to_string(),
+'mime_type': 'text/uri-list',
+}
+for k, v in metadata.items():
+jobject.metadata[k] = v
+file_path = join(get_activity_root(), 'instance', '%i_' % time.time())
+open(file_path, 'w').write(url + '\r\n')
+os.chmod(file_path, 0755)
+jobject.set_file_path(file_path)
+datastore.write(jobject)
+show_object_in_journal(jobject.object_id)
+jobject.destroy()
+os.unlink(file_path)
+
+# Looks at all tags covering the position (x, y) in the text view,
+# and if one of them is a link return True
+def check_url_hovering(self, x, y):
+hovering = False
+self.palette = None
+iter_tags = self.get_iter_at_location(x, y)
+
+tags = iter_tags.get_tags()
+for tag in tags:
+url = tag.get_data('url')
+self.palette = tag.get_data('palette')
+if url is not None:
+hovering = True
+break
+return hovering
+
+# Looks at all tags covering the position (x, y) in the text view,
+# and if one of them is a link, change the cursor to the hands cursor
+def set_cursor_if_appropriate(self, x, y):
+hovering_over_link = self.check_url_hovering(x, y)
+win = 

[Sugar-devel] [PATCH] Start filtered activity with keyboard

2011-11-07 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This patch complement the filter functionality in the home view.
If only one activity is selected, Return key start the activity.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/favoritesview.py |7 +++
 src/jarabe/desktop/homewindow.py|2 ++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/desktop/favoritesview.py 
b/src/jarabe/desktop/favoritesview.py
index 132d14f..db3aa36 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -94,6 +94,7 @@ class FavoritesView(hippo.Canvas):
 self._layout = None
 self._alert = None
 self._resume_mode = True
+self._filtered_icons = []
 
 # More DND stuff
 self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
@@ -113,14 +114,20 @@ class FavoritesView(hippo.Canvas):
 
 def set_filter(self, query):
 query = query.strip()
+self._filtered_icons = []
 for icon in self._box.get_children():
 if icon not in [self._my_icon, self._current_activity]:
 activity_name = icon._activity_info.get_name().lower()
 if activity_name.find(query)  -1:
 icon.alpha = 1.0
+self._filtered_icons.append(icon)
 else:
 icon.alpha = 0.33
 
+def start_selected_activity(self):
+if len(self._filtered_icons) == 1:
+self._filtered_icons[0]._activate()
+
 def __settings_changed_cb(self, **kwargs):
 favorites_settings = get_settings()
 self._set_layout(favorites_settings.layout)
diff --git a/src/jarabe/desktop/homewindow.py b/src/jarabe/desktop/homewindow.py
index 07deff7..f03b067 100644
--- a/src/jarabe/desktop/homewindow.py
+++ b/src/jarabe/desktop/homewindow.py
@@ -117,6 +117,8 @@ class HomeWindow(gtk.Window):
 def __key_press_event_cb(self, window, event):
 if event.keyval in [gtk.keysyms.Alt_L, gtk.keysyms.Alt_R]:
 self._home_box.set_resume_mode(False)
+if event.keyval == gtk.keysyms.Return:
+self._home_box._favorites_view.start_selected_activity()
 return False
 
 def __key_release_event_cb(self, window, event):
-- 
1.7.7

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Disable the search entry in the activities list view and in the Journal - SL #3205

2011-10-20 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

If not disabled, a entry appear over the treeview at bottom, right
when the user type something and the widget have focus.
The ObjectChooser use the same object than the Journal.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/activitieslist.py |1 +
 src/jarabe/journal/listview.py   |1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/desktop/activitieslist.py 
b/src/jarabe/desktop/activitieslist.py
index b3b1f9d..7bf0960 100644
--- a/src/jarabe/desktop/activitieslist.py
+++ b/src/jarabe/desktop/activitieslist.py
@@ -116,6 +116,7 @@ class ActivitiesTreeView(gtk.TreeView):
 self.append_column(column)
 
 self.set_search_column(ListModel.COLUMN_TITLE)
+self.set_enable_search(False)
 
 def __erase_activated_cb(self, cell_renderer, bundle_id):
 self.emit('erase-activated', bundle_id)
diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py
index a0ceccc..57836f2 100644
--- a/src/jarabe/journal/listview.py
+++ b/src/jarabe/journal/listview.py
@@ -44,6 +44,7 @@ class TreeView(gtk.TreeView):
 def __init__(self):
 gtk.TreeView.__init__(self)
 self.set_headers_visible(False)
+self.set_enable_search(False)
 
 def do_size_request(self, requisition):
 # HACK: We tell the model that the view is just resizing so it can
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Update alpha according to filter after events in neighborhoodview icons - SL #3091 -v2

2011-10-07 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The neighboard view use alpha to show the applied filter.
When the state of a ap change the graphic representation
is updated and the alpha should be restored acording the filter value.

v2 - As suggested by Simon by irc,moved the call to update_color in the class
OlpcMeshView to  __device_state_changed_cb

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/networkviews.py |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/desktop/networkviews.py 
b/src/jarabe/desktop/networkviews.py
index 616f555..677452d 100644
--- a/src/jarabe/desktop/networkviews.py
+++ b/src/jarabe/desktop/networkviews.py
@@ -149,6 +149,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
 self._update_state()
 self._update_icon()
 self._update_badge()
+self._update_color()
 
 def __update_active_ap(self, ap_path):
 if ap_path in self._access_points:
@@ -558,6 +559,7 @@ class SugarAdhocView(CanvasPulsingIcon):
 self._connect_item.show()
 self._palette.props.secondary_text = None
 self.props.pulsing = False
+self._update_color()
 
 def _update_color(self):
 self.props.base_color = self._state_color
@@ -650,6 +652,7 @@ class OlpcMeshView(CanvasPulsingIcon):
 def __device_state_changed_cb(self, new_state, old_state, reason):
 self._device_state = new_state
 self._update()
+self._update_color()
 
 def __get_active_channel_reply_cb(self, channel):
 self._active = (channel == self._channel)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Pippy] Fix the load of already saved examples

2011-10-06 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The local examples are saved but are not loaded again when the activity starts.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 pippy_app.py |   11 +--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/pippy_app.py b/pippy_app.py
index 3a0317d..909512f 100644
--- a/pippy_app.py
+++ b/pippy_app.py
@@ -222,12 +222,19 @@ class PippyActivity(ViewSourceActivity, 
groupthink.sugar_tools.GroupActivity):
 self.model.set_value(_iter, 0, entry)
 self.model.set_value(_iter, 1, entry[name])
 # Adding local examples 
-#d = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data') 
+root = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data')
 direntry_examples  = { name: _(My examples), 
-   path: os.path.join(root, d) + / } 
+   path: root + / }
 self.example_iter = self.model.insert_before(None, None) 
 self.model.set_value(self.example_iter, 0, direntry_examples) 
 self.model.set_value(self.example_iter, 1, direntry_examples[name]) 
+for _file in sorted(os.listdir(root)):
+file_name = os.path.join(root, _file)
+if os.path.isfile(file_name):
+entry = {name: _file, path: file_name}
+_iter = self.model.insert_before(self.example_iter, None)
+self.model.set_value(_iter, 0, entry)
+self.model.set_value(_iter, 1, entry[name])
 
 treeview.expand_all()
 
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Record] Fix tooltips in radio buttons

2011-10-03 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 record.py |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/record.py b/record.py
index 5c06f20..dba46af 100644
--- a/record.py
+++ b/record.py
@@ -137,7 +137,7 @@ class Record(activity.Activity):
 self._photo_button.props.group = tool_group
 tool_group = self._photo_button
 self._photo_button.props.icon_name = 'camera-external'
-self._photo_button.props.label = _('Photo')
+self._photo_button.set_tooltip(_('Photo'))
 self._photo_button.mode = constants.MODE_PHOTO
 self._photo_button.connect('clicked', self._mode_button_clicked)
 self._toolbar.insert(self._photo_button, -1)
@@ -145,7 +145,7 @@ class Record(activity.Activity):
 self._video_button = RadioToolButton()
 self._video_button.props.group = tool_group
 self._video_button.props.icon_name = 'media-video'
-self._video_button.props.label = _('Video')
+self._video_button.set_tooltip(_('Video'))
 self._video_button.mode = constants.MODE_VIDEO
 self._video_button.connect('clicked', self._mode_button_clicked)
 self._toolbar.insert(self._video_button, -1)
@@ -156,7 +156,7 @@ class Record(activity.Activity):
 self._audio_button = RadioToolButton()
 self._audio_button.props.group = tool_group
 self._audio_button.props.icon_name = 'media-audio'
-self._audio_button.props.label = _('Audio')
+self._audio_button.set_tooltip(_('Audio'))
 self._audio_button.mode = constants.MODE_AUDIO
 self._audio_button.connect('clicked', self._mode_button_clicked)
 self._toolbar.insert(self._audio_button, -1)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Browse] Use named parameters to enable translation in msg with multiple strings

2011-09-30 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 downloadmanager.py |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/downloadmanager.py b/downloadmanager.py
index 0fd6537..98d4f1a 100644
--- a/downloadmanager.py
+++ b/downloadmanager.py
@@ -341,8 +341,9 @@ class Download:
 
 def _create_journal_object(self):
 self.dl_jobject = datastore.create()
-self.dl_jobject.metadata['title'] = _('Downloading %s from \n%s.') % \
-(self._get_file_name(), self._source.spec)
+self.dl_jobject.metadata['title'] = \
+_('Downloading %(file)s from \n%(source)s.') % \
+{'file': self._get_file_name(), 'source': self._source.spec}
 
 self.dl_jobject.metadata['progress'] = '0'
 self.dl_jobject.metadata['keep'] = '0'
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Update alpha according to filter after events in neighborhoodview icons - SL #3091

2011-09-22 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/networkviews.py |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/desktop/networkviews.py 
b/src/jarabe/desktop/networkviews.py
index 616f555..055f2ed 100644
--- a/src/jarabe/desktop/networkviews.py
+++ b/src/jarabe/desktop/networkviews.py
@@ -149,6 +149,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
 self._update_state()
 self._update_icon()
 self._update_badge()
+self._update_color()
 
 def __update_active_ap(self, ap_path):
 if ap_path in self._access_points:
@@ -558,6 +559,7 @@ class SugarAdhocView(CanvasPulsingIcon):
 self._connect_item.show()
 self._palette.props.secondary_text = None
 self.props.pulsing = False
+self._update_color()
 
 def _update_color(self):
 self.props.base_color = self._state_color
@@ -691,6 +693,7 @@ class OlpcMeshView(CanvasPulsingIcon):
 self._connect_item.show()
 self._palette.props.secondary_text = None
 self.props.pulsing = False
+self._update_color()
 
 def _update_color(self):
 self.props.base_color = profile.get_color()
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [Memorize PATCH 2/2] Implement new toolbar in Memorize

2011-09-07 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 activity.py|  127 +++--
 cardlist.py|2 +-
 createtoolbar.py   |  161 +---
 game.py|1 -
 memorizetoolbar.py |   49 +---
 5 files changed, 166 insertions(+), 174 deletions(-)

diff --git a/activity.py b/activity.py
index 81c36ae..4fcc2e4 100644
--- a/activity.py
+++ b/activity.py
@@ -33,6 +33,10 @@ import gtk
 import telepathy
 import telepathy.client
 
+from sugar.activity.widgets import ActivityToolbarButton
+from sugar.activity.widgets import StopButton
+from sugar.graphics.toolbarbox import ToolbarButton, ToolbarBox
+
 from sugar.activity.activity import Activity, ActivityToolbox
 from sugar.presence import presenceservice
 from sugar.presence.tubeconn import TubeConnection
@@ -52,34 +56,60 @@ SERVICE = 'org.laptop.Memorize'
 IFACE = SERVICE
 PATH = '/org/laptop/Memorize'
 
-_TOOLBAR_PLAY = 1
-_TOOLBAR_CREATE = 2
+_MODE_PLAY = 1
+_MODE_CREATE = 2
 
 class MemorizeActivity(Activity):
 
 def __init__(self, handle):
 Activity.__init__(self, handle)
 
-self.create_load = False
 self.play_mode = None
 
-toolbox = ActivityToolbox(self)
-activity_toolbar = toolbox.get_activity_toolbar()
-
-self._memorizeToolbar = memorizetoolbar.MemorizeToolbar(self)
-toolbox.add_toolbar(_('Play'), self._memorizeToolbar)
-self._memorizeToolbar.show()  
+toolbar_box = ToolbarBox()
+self.set_toolbar_box(toolbar_box)
+
+self.activity_button = ActivityToolbarButton(self)
+toolbar_box.toolbar.insert(self.activity_button, -1)
+
+self._memorizeToolbarBuilder = \
+memorizetoolbar.MemorizeToolbarBuilder(self)
+
+toolbar_box.toolbar.insert(gtk.SeparatorToolItem(), -1)
+
+self._createToolbarBuilder = \
+createtoolbar.CreateToolbarBuilder(self)
+
+separator = gtk.SeparatorToolItem()
+separator.set_expand(True)
+separator.set_draw(False)
+toolbar_box.toolbar.insert(separator, -1)
+
+toolbar_box.toolbar.insert(StopButton(self), -1)
 
-self._createToolbar = createtoolbar.CreateToolbar(self)
-toolbox.add_toolbar(_('Create'), self._createToolbar)
-self._createToolbar.show()
-
-self.set_toolbox(toolbox)
-toolbox.show()
-
 # Play game mode
 self.table = cardtable.CardTable()
 self.scoreboard = scoreboard.Scoreboard()
+self.cardlist = cardlist.CardList()
+self.createcardpanel = createcardpanel.CreateCardPanel()
+self.cardlist.connect('pair-selected',
+self.createcardpanel.pair_selected)
+self.cardlist.connect('update-create-toolbar',
+self._createToolbarBuilder.update_create_toolbar)
+self.cardlist.connect('update-create-buttons',
+self._createToolbarBuilder.update_buttons_status)
+self.createcardpanel.connect('add-pair',
+self.cardlist.add_pair)
+self.createcardpanel.connect('update-pair',
+self.cardlist.update_selected)
+self._createToolbarBuilder.connect('create_new_game',
+self.cardlist.clean_list)
+self._createToolbarBuilder.connect('create_new_game',
+self.createcardpanel.clean)
+self._createToolbarBuilder.connect('create_save_game',
+self.cardlist.save_game)
+self._createToolbarBuilder.connect('create_equal_pairs',
+self.createcardpanel.change_equal_pairs)
 self.game = game.MemorizeGame()
 
 self.table.connect('key-press-event', self.table.key_press_event)
@@ -107,10 +137,13 @@ class MemorizeActivity(Activity):
 
 self.game.connect('load_game', self.table.load_game)
 self.game.connect('change_game', self.table.change_game)
-self.game.connect('load_game', self._memorizeToolbar.update_toolbar)
-self.game.connect('change_game', self._memorizeToolbar.update_toolbar)
-
-self._memorizeToolbar.connect('game_changed', self.game.change_game)
+self.game.connect('load_game',
+self._memorizeToolbarBuilder.update_toolbar)
+self.game.connect('change_game',
+self._memorizeToolbarBuilder.update_toolbar)
+
+self._memorizeToolbarBuilder.connect('game_changed',
+self.change_game)
 
 self.hbox = gtk.HBox(False)
 self.set_canvas(self.hbox)
@@ -126,8 +159,10 @@ class MemorizeActivity(Activity):
 
 # start on the game toolbar, might change this
 # to the create toolbar later
-self.toolbox.connect('current-toolbar-changed', self.change_mode)
-self.toolbox.set_current_toolbar(_TOOLBAR_PLAY)
+# TODO:
+

[Sugar-devel] [PATCH Distance] Restore returned value of function accidentaly removed - SL #3072

2011-09-02 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Was removed in ca967f89dc3a649caca9ca1226d24fd03a14d25e

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 arange.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arange.py b/arange.py
index 4a0e096..4704c83 100644
--- a/arange.py
+++ b/arange.py
@@ -136,7 +136,7 @@ def write_wav(o):
 q[::2] = o*255
 q[1::2] = 128
 w.writeframes(q.tostring())
-return 
+return f
 
 def play_wav_alsa(fname):
 subprocess.call([/usr/bin/aplay, fname])
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Fix format string to the factor conversion label

2011-09-02 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 smoot_toolbar.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/smoot_toolbar.py b/smoot_toolbar.py
index 5e77566..91bc85a 100644
--- a/smoot_toolbar.py
+++ b/smoot_toolbar.py
@@ -101,7 +101,7 @@ class SmootToolbar(gtk.Toolbar):
 if name == _('meters'):
 self._factor_label.set_label(' ')
 else:
-self._factor_label.set_label(_('%2$0.2f %1$s per meter') % (
+self._factor_label.set_label(_('%20.2f %1s per meter') % (
 self._unit_scale, name))
 
 def get_scale(self):
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Fix factor in centimeters unit

2011-09-02 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 smoot_toolbar.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/smoot_toolbar.py b/smoot_toolbar.py
index 91bc85a..649050c 100644
--- a/smoot_toolbar.py
+++ b/smoot_toolbar.py
@@ -32,7 +32,7 @@ UNITS = [_('meters'), _('centimeters'),
  _('inches'), _('feet'), _('yards'),
  _('custom units')]
 UNIT_DICTIONARY = {METERS: (_('meters'), 1.0),
-   CENTIMETERS: (_('centimeters'), 10.0),
+   CENTIMETERS: (_('centimeters'), 100.0),
INCHES: (_('inches'), 39.37),
FEET: (_('feet'), 3.28),
YARDS: (_('yards'), 1.09),
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH 3/4] Use iconentry.ICON_ENTRY_SECONDARY instead of gtk.ENTRY_ICON_SECONDARY by compatibility

2011-08-30 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 webtoolbar.py |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/webtoolbar.py b/webtoolbar.py
index e5af3ea..dfb178f 100644
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -25,7 +25,7 @@ from xpcom.components import interfaces
 
 from sugar.graphics.toolbutton import ToolButton
 from sugar.graphics.menuitem import MenuItem
-from sugar.graphics.iconentry import IconEntry
+from sugar.graphics import iconentry
 try:
 from sugar.graphics.toolbarbox import ToolbarBox as ToolbarBase
 from sugar.activity.widgets import ActivityToolbarButton
@@ -42,7 +42,7 @@ import places
 _MAX_HISTORY_ENTRIES = 15
 
 
-class WebEntry(IconEntry):
+class WebEntry(iconentry.IconEntry):
 _COL_ADDRESS = 0
 _COL_TITLE = 1
 
@@ -260,7 +260,7 @@ class PrimaryToolbar(ToolbarBase):
 self._go_home.show()
 
 self.entry = WebEntry()
-self.entry.set_icon_from_name(gtk.ENTRY_ICON_SECONDARY,
+self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
   'browse-dialog-cancel')
 self.entry.connect('icon-press', self._stop_and_reload_cb)
 self.entry.connect('activate', self._entry_activate_cb)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Browse] Use iconentry.ICON_ENTRY_SECONDARY instead of gtk.ENTRY_ICON_SECONDARY by compatibility

2011-08-30 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 webtoolbar.py |   10 +-
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/webtoolbar.py b/webtoolbar.py
index e5af3ea..b84332d 100644
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -25,7 +25,7 @@ from xpcom.components import interfaces
 
 from sugar.graphics.toolbutton import ToolButton
 from sugar.graphics.menuitem import MenuItem
-from sugar.graphics.iconentry import IconEntry
+from sugar.graphics import iconentry
 try:
 from sugar.graphics.toolbarbox import ToolbarBox as ToolbarBase
 from sugar.activity.widgets import ActivityToolbarButton
@@ -42,7 +42,7 @@ import places
 _MAX_HISTORY_ENTRIES = 15
 
 
-class WebEntry(IconEntry):
+class WebEntry(iconentry.IconEntry):
 _COL_ADDRESS = 0
 _COL_TITLE = 1
 
@@ -260,7 +260,7 @@ class PrimaryToolbar(ToolbarBase):
 self._go_home.show()
 
 self.entry = WebEntry()
-self.entry.set_icon_from_name(gtk.ENTRY_ICON_SECONDARY,
+self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
   'browse-dialog-cancel')
 self.entry.connect('icon-press', self._stop_and_reload_cb)
 self.entry.connect('activate', self._entry_activate_cb)
@@ -397,11 +397,11 @@ class PrimaryToolbar(ToolbarBase):
 self.entry.props.title = title
 
 def _show_stop_icon(self):
-self.entry.set_icon_from_name(gtk.ENTRY_ICON_SECONDARY,
+self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
   'browse-dialog-cancel')
 
 def _show_reload_icon(self):
-self.entry.set_icon_from_name(gtk.ENTRY_ICON_SECONDARY,
+self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
   'browse-view-refresh')
 
 def _update_navigation_buttons(self):
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Manage the Documents folder in the VolumesToolbar

2011-08-26 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

After adding the Documents folder in the VolumesToolbar,
if the user unmount a device with the ObjectChooser opened,
the code break and the device button is not removed.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/journal/volumestoolbar.py |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/jarabe/journal/volumestoolbar.py 
b/src/jarabe/journal/volumestoolbar.py
index 7a34e18..36f3011 100644
--- a/src/jarabe/journal/volumestoolbar.py
+++ b/src/jarabe/journal/volumestoolbar.py
@@ -280,7 +280,8 @@ class VolumesToolbar(gtk.Toolbar):
 def _get_button_for_mount(self, mount):
 mount_point = mount.get_root().get_path()
 for button in self.get_children():
-if button.mount_point == mount_point:
+if hasattr(button, 'mount_point') and \
+button.mount_point == mount_point:
 return button
 logging.error('Couldnt find button with mount_point %r', mount_point)
 return None
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Change string Remove in device palette by Remove device

2011-08-24 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This more specific string, help solve translationes where Remove does not
have the same meaning. In Spanish, for example the translation Eliminar
means Destroy and must be used Quitar meaning take out.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/view/palettes.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/jarabe/view/palettes.py b/src/jarabe/view/palettes.py
index d9c1f6b..5223858 100644
--- a/src/jarabe/view/palettes.py
+++ b/src/jarabe/view/palettes.py
@@ -217,7 +217,7 @@ class VolumePalette(Palette):
 
 self.connect('popup', self.__popup_cb)
 
-menu_item = MenuItem(_('Remove'))
+menu_item = MenuItem(_('Remove device'))
 
 icon = Icon(icon_name='media-eject', icon_size=gtk.ICON_SIZE_MENU)
 menu_item.set_image(icon)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Implement filter in favorites view - v2

2011-08-18 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The icons of non selected activities are painted in light gray
like in the neighborhood view. The user can interact with them
because are not disabled, the filter only highligt the selected activities.

Signed-of-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/favoritesview.py |   18 +++---
 src/jarabe/desktop/homebox.py   |   22 +-
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/src/jarabe/desktop/favoritesview.py 
b/src/jarabe/desktop/favoritesview.py
index b609b1b..2ae44c6 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -110,6 +110,16 @@ class FavoritesView(hippo.Canvas):
 favorites_settings.changed.connect(self.__settings_changed_cb)
 self._set_layout(favorites_settings.layout)
 
+def set_filter(self, query):
+for icon in self._box.get_children():
+if icon not in [self._my_icon, self._current_activity]:
+activity_name = icon._activity_info.get_name().lower()
+if activity_name.find(query)  -1:
+icon.props.xo_color = icon.icon_color
+else:
+icon.props.xo_color = XoColor('#D5D5D5,%s' %
+   style.COLOR_TRANSPARENT.get_svg())
+
 def __settings_changed_cb(self, **kwargs):
 favorites_settings = get_settings()
 self._set_layout(favorites_settings.layout)
@@ -362,6 +372,7 @@ class ActivityIcon(CanvasIcon):
 self._journal_entries = []
 self._hovering = False
 self._resume_mode = True
+self.icon_color = None
 
 self.connect('hovering-changed', self.__hovering_changed_event_cb)
 self.connect('button-release-event', self.__button_release_event_cb)
@@ -414,11 +425,12 @@ class ActivityIcon(CanvasIcon):
 def _update(self):
 self.palette = None
 if not self._resume_mode or not self._journal_entries:
-xo_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
+self.icon_color = XoColor('%s,%s' %
+(style.COLOR_BUTTON_GREY.get_svg(),
   style.COLOR_TRANSPARENT.get_svg()))
 else:
-xo_color = misc.get_icon_color(self._journal_entries[0])
-self.props.xo_color = xo_color
+self.icon_color = misc.get_icon_color(self._journal_entries[0])
+self.props.xo_color = self.icon_color
 
 def create_palette(self):
 palette = FavoritePalette(self._activity_info, self._journal_entries)
diff --git a/src/jarabe/desktop/homebox.py b/src/jarabe/desktop/homebox.py
index 661326e..2ee6ae7 100644
--- a/src/jarabe/desktop/homebox.py
+++ b/src/jarabe/desktop/homebox.py
@@ -55,6 +55,7 @@ class HomeBox(gtk.VBox):
 self._toolbar.show()
 
 self._set_view(_FAVORITES_VIEW)
+self._query = ''
 
 def show_software_updates_alert(self):
 alert = Alert()
@@ -103,8 +104,9 @@ class HomeBox(gtk.VBox):
 panel.set_section_view_auto_close()
 
 def __toolbar_query_changed_cb(self, toolbar, query):
-query = query.lower()
-self._list_view.set_filter(query)
+self._query = query.lower()
+self._list_view.set_filter(self._query)
+self._favorites_view.set_filter(self._query)
 
 def __toolbar_view_changed_cb(self, toolbar, view):
 self._set_view(view)
@@ -145,6 +147,9 @@ class HomeBox(gtk.VBox):
 
 def set_resume_mode(self, resume_mode):
 self._favorites_view.set_resume_mode(resume_mode)
+if resume_mode and self._query != '':
+self._list_view.set_filter(self._query)
+self._favorites_view.set_filter(self._query)
 
 
 class HomeToolbar(gtk.Toolbar):
@@ -177,7 +182,6 @@ class HomeToolbar(gtk.Toolbar):
 self.search_entry.connect('activate', self.__entry_activated_cb)
 self.search_entry.connect('changed', self.__entry_changed_cb)
 tool_item.add(self.search_entry)
-self.search_entry.set_sensitive(False)
 self.search_entry.show()
 
 self._add_separator(expand=True)
@@ -201,14 +205,8 @@ class HomeToolbar(gtk.Toolbar):
 
 def __view_button_toggled_cb(self, button, view):
 if button.props.active:
-if view == _FAVORITES_VIEW:
-self.search_entry.set_text('')
-self.search_entry.set_sensitive(False)
-self.emit('view-changed', view)
-else:
-self.search_entry.set_sensitive(True)
-self.search_entry.grab_focus()
-self.emit('view-changed', view)
+self.search_entry.grab_focus()
+self.emit('view-changed', view)
 
 def _add_separator(self, expand=False):
 separator = gtk.SeparatorToolItem()
@@ -228,8 +226,6 @@ class HomeToolbar(gtk.Toolbar):
 if self._query != 

[Sugar-devel] [PATCH] Implement filter in favorites view - v3

2011-08-18 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

After evaluation with Design Team, the filter higlight selected
activities applying a alpha of 0.33 in the unselected activities.
This patch add strip() to the query to avoid accidental filtering
of all activities by adding spaces.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/favoritesview.py |   10 ++
 src/jarabe/desktop/homebox.py   |   22 +-
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/jarabe/desktop/favoritesview.py 
b/src/jarabe/desktop/favoritesview.py
index b609b1b..1be7d76 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -110,6 +110,16 @@ class FavoritesView(hippo.Canvas):
 favorites_settings.changed.connect(self.__settings_changed_cb)
 self._set_layout(favorites_settings.layout)
 
+def set_filter(self, query):
+query = query.strip()
+for icon in self._box.get_children():
+if icon not in [self._my_icon, self._current_activity]:
+activity_name = icon._activity_info.get_name().lower()
+if activity_name.find(query)  -1:
+icon.alpha = 1.0
+else:
+icon.alpha = 0.33
+
 def __settings_changed_cb(self, **kwargs):
 favorites_settings = get_settings()
 self._set_layout(favorites_settings.layout)
diff --git a/src/jarabe/desktop/homebox.py b/src/jarabe/desktop/homebox.py
index 661326e..2ee6ae7 100644
--- a/src/jarabe/desktop/homebox.py
+++ b/src/jarabe/desktop/homebox.py
@@ -55,6 +55,7 @@ class HomeBox(gtk.VBox):
 self._toolbar.show()
 
 self._set_view(_FAVORITES_VIEW)
+self._query = ''
 
 def show_software_updates_alert(self):
 alert = Alert()
@@ -103,8 +104,9 @@ class HomeBox(gtk.VBox):
 panel.set_section_view_auto_close()
 
 def __toolbar_query_changed_cb(self, toolbar, query):
-query = query.lower()
-self._list_view.set_filter(query)
+self._query = query.lower()
+self._list_view.set_filter(self._query)
+self._favorites_view.set_filter(self._query)
 
 def __toolbar_view_changed_cb(self, toolbar, view):
 self._set_view(view)
@@ -145,6 +147,9 @@ class HomeBox(gtk.VBox):
 
 def set_resume_mode(self, resume_mode):
 self._favorites_view.set_resume_mode(resume_mode)
+if resume_mode and self._query != '':
+self._list_view.set_filter(self._query)
+self._favorites_view.set_filter(self._query)
 
 
 class HomeToolbar(gtk.Toolbar):
@@ -177,7 +182,6 @@ class HomeToolbar(gtk.Toolbar):
 self.search_entry.connect('activate', self.__entry_activated_cb)
 self.search_entry.connect('changed', self.__entry_changed_cb)
 tool_item.add(self.search_entry)
-self.search_entry.set_sensitive(False)
 self.search_entry.show()
 
 self._add_separator(expand=True)
@@ -201,14 +205,8 @@ class HomeToolbar(gtk.Toolbar):
 
 def __view_button_toggled_cb(self, button, view):
 if button.props.active:
-if view == _FAVORITES_VIEW:
-self.search_entry.set_text('')
-self.search_entry.set_sensitive(False)
-self.emit('view-changed', view)
-else:
-self.search_entry.set_sensitive(True)
-self.search_entry.grab_focus()
-self.emit('view-changed', view)
+self.search_entry.grab_focus()
+self.emit('view-changed', view)
 
 def _add_separator(self, expand=False):
 separator = gtk.SeparatorToolItem()
@@ -228,8 +226,6 @@ class HomeToolbar(gtk.Toolbar):
 if self._query != new_query:
 self._query = new_query
 
-if self._query is not '':
-self._list_button.props.active = True
 self.emit('query-changed', self._query)
 
 def __entry_changed_cb(self, entry):
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Use alpha to visualize filter in neighborhood view

2011-08-18 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Apply a alpha of 0.33 to unfiltered items to have consistency
with the filter in te favorites view.

Signed-of-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/networkviews.py |   39 +--
 1 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/src/jarabe/desktop/networkviews.py 
b/src/jarabe/desktop/networkviews.py
index 99d46b6..4935082 100644
--- a/src/jarabe/desktop/networkviews.py
+++ b/src/jarabe/desktop/networkviews.py
@@ -54,6 +54,7 @@ _NM_ACTIVE_CONN_IFACE = 
'org.freedesktop.NetworkManager.Connection.Active'
 _AP_ICON_NAME = 'network-wireless'
 _OLPC_MESH_ICON_NAME = 'network-mesh'
 
+_FILTERED_ALPHA = 0.33
 
 class WirelessNetworkView(CanvasPulsingIcon):
 def __init__(self, initial_ap):
@@ -66,7 +67,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
 self._palette_icon = None
 self._disconnect_item = None
 self._connect_item = None
-self._greyed_out = False
+self._filtered = False
 self._name = initial_ap.name
 self._mode = initial_ap.mode
 self._strength = initial_ap.strength
@@ -258,11 +259,12 @@ class WirelessNetworkView(CanvasPulsingIcon):
 self.props.pulsing = False
 
 def _update_color(self):
-if self._greyed_out:
+self.props.base_color = self._color
+if self._filtered:
 self.props.pulsing = False
-self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
+self.alpha = _FILTERED_ALPHA
 else:
-self.props.base_color = self._color
+self.alpha = 1.0
 
 def _disconnect_activate_cb(self, item):
 if self._mode == network.NM_802_11_MODE_INFRA:
@@ -383,7 +385,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
 logging.error('Failed to activate connection: %s', err)
 
 def set_filter(self, query):
-self._greyed_out = self._name.lower().find(query) == -1
+self._filtered = self._name.lower().find(query) == -1
 self._update_icon()
 self._update_color()
 
@@ -469,7 +471,7 @@ class SugarAdhocView(CanvasPulsingIcon):
 self._disconnect_item = None
 self._connect_item = None
 self._palette_icon = None
-self._greyed_out = False
+self._filtered = False
 
 get_adhoc_manager_instance().connect('members-changed',
  self.__members_changed_cb)
@@ -556,11 +558,12 @@ class SugarAdhocView(CanvasPulsingIcon):
 self.props.pulsing = False
 
 def _update_color(self):
-if self._greyed_out:
+self.props.base_color = self._state_color
+if self._filtered:
 self.props.pulsing = False
-self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
+self.alpha = _FILTERED_ALPHA
 else:
-self.props.base_color = self._state_color
+self.alpha = 1.0
 
 def __members_changed_cb(self, adhoc_manager, channel, has_members):
 if channel == self._channel:
@@ -571,13 +574,16 @@ class SugarAdhocView(CanvasPulsingIcon):
style.COLOR_TRANSPARENT.get_svg())
 self._state_color = XoColor(color)
 
-if not self._greyed_out:
+if not self._filtered:
 self.props.base_color = self._state_color
 self._palette_icon.props.xo_color = self._state_color
+self.alpha = 1.0
+else:
+self.alpha = _FILTERED_ALPHA
 
 def set_filter(self, query):
 name = self._NAME + str(self._channel)
-self._greyed_out = name.lower().find(query) == -1
+self._filtered = name.lower().find(query) == -1
 self._update_color()
 
 
@@ -590,7 +596,7 @@ class OlpcMeshView(CanvasPulsingIcon):
 self._mesh_mgr = mesh_mgr
 self._disconnect_item = None
 self._connect_item = None
-self._greyed_out = False
+self._filtered = False
 self._name = ''
 self._device_state = None
 self._active = False
@@ -684,10 +690,11 @@ class OlpcMeshView(CanvasPulsingIcon):
 self.props.pulsing = False
 
 def _update_color(self):
-if self._greyed_out:
-self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
+self.props.base_color = profile.get_color()
+if self._filtered:
+self.alpha = _FILTERED_ALPHA
 else:
-self.props.base_color = profile.get_color()
+self.alpha = 1.0
 
 def __connect_activate_cb(self, icon):
 self._connect()
@@ -705,7 +712,7 @@ class OlpcMeshView(CanvasPulsingIcon):
 logging.error('Failed to activate connection: %s', err)
 
 def set_filter(self, query):
-self._greyed_out = (query != '')
+self._filtered = (query != '')
 self._update_color()
 
 def disconnect(self):
-- 
1.7.4.4


[Sugar-devel] [PATCH Terminal] Remove code setting accelerator to KeepButton because was removed from defualt toolbar

2011-08-17 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 terminal.py |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/terminal.py b/terminal.py
index bfae031..9b2b68e 100644
--- a/terminal.py
+++ b/terminal.py
@@ -59,7 +59,6 @@ class TerminalActivity(activity.Activity):
 
 activity_button = ActivityToolbarButton(self)
 toolbar_box.toolbar.insert(activity_button, 0)
-activity_button.page.keep.props.accelerator = 'CtrlShiftS'
 activity_button.show()
 
 edit_toolbar = self._create_edit_toolbar()
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Avoid adding multiple times the callback to the duplicate button

2011-08-17 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The effect of adding multiple times the callback is
the first file the user duplicate, create one copy,
the second create two copies, the third three copies...

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/journal/journaltoolbox.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/jarabe/journal/journaltoolbox.py 
b/src/jarabe/journal/journaltoolbox.py
index b6f8ef8..cdf6a77 100644
--- a/src/jarabe/journal/journaltoolbox.py
+++ b/src/jarabe/journal/journaltoolbox.py
@@ -387,6 +387,7 @@ class EntryToolbar(gtk.Toolbar):
 icon = Icon(icon_name='edit-duplicate', xo_color=color)
 self._duplicate.set_icon_widget(icon)
 self._duplicate.set_tooltip(_('Duplicate'))
+self._duplicate.connect('clicked', self._duplicate_clicked_cb)
 self.add(self._duplicate)
 
 separator = gtk.SeparatorToolItem()
@@ -477,7 +478,6 @@ class EntryToolbar(gtk.Toolbar):
 color = misc.get_icon_color(self._metadata)
 self._copy.get_icon_widget().props.xo_color = color
 if self._metadata['mountpoint'] == '/':
-self._duplicate.connect('clicked', self._duplicate_clicked_cb)
 self._duplicate.show()
 icon = self._duplicate.get_icon_widget()
 icon.props.xo_color = color
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH sugar] Implement filter in the favorites view

2011-08-14 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The patch change the alpha value of the activities icons
acording to the filter to highlight the requested activities.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/desktop/favoritesview.py |   10 ++
 src/jarabe/desktop/homebox.py   |   14 +++---
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/src/jarabe/desktop/favoritesview.py 
b/src/jarabe/desktop/favoritesview.py
index b609b1b..beb123e 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -110,6 +110,16 @@ class FavoritesView(hippo.Canvas):
 favorites_settings.changed.connect(self.__settings_changed_cb)
 self._set_layout(favorites_settings.layout)
 
+def set_filter(self, query):
+logging.debug(set filter query:%s, query)
+for icon in self._box.get_children():
+if icon not in [self._my_icon, self._current_activity]:
+activity_name = icon._activity_info.get_name().lower()
+if activity_name.find(query)  -1:
+icon.alpha = 1.0
+else:
+icon.alpha = 0.2
+
 def __settings_changed_cb(self, **kwargs):
 favorites_settings = get_settings()
 self._set_layout(favorites_settings.layout)
diff --git a/src/jarabe/desktop/homebox.py b/src/jarabe/desktop/homebox.py
index 661326e..c7e88ad 100644
--- a/src/jarabe/desktop/homebox.py
+++ b/src/jarabe/desktop/homebox.py
@@ -105,6 +105,7 @@ class HomeBox(gtk.VBox):
 def __toolbar_query_changed_cb(self, toolbar, query):
 query = query.lower()
 self._list_view.set_filter(query)
+self._favorites_view.set_filter(query)
 
 def __toolbar_view_changed_cb(self, toolbar, view):
 self._set_view(view)
@@ -177,7 +178,6 @@ class HomeToolbar(gtk.Toolbar):
 self.search_entry.connect('activate', self.__entry_activated_cb)
 self.search_entry.connect('changed', self.__entry_changed_cb)
 tool_item.add(self.search_entry)
-self.search_entry.set_sensitive(False)
 self.search_entry.show()
 
 self._add_separator(expand=True)
@@ -201,14 +201,8 @@ class HomeToolbar(gtk.Toolbar):
 
 def __view_button_toggled_cb(self, button, view):
 if button.props.active:
-if view == _FAVORITES_VIEW:
-self.search_entry.set_text('')
-self.search_entry.set_sensitive(False)
-self.emit('view-changed', view)
-else:
-self.search_entry.set_sensitive(True)
-self.search_entry.grab_focus()
-self.emit('view-changed', view)
+self.search_entry.grab_focus()
+self.emit('view-changed', view)
 
 def _add_separator(self, expand=False):
 separator = gtk.SeparatorToolItem()
@@ -228,8 +222,6 @@ class HomeToolbar(gtk.Toolbar):
 if self._query != new_query:
 self._query = new_query
 
-if self._query is not '':
-self._list_button.props.active = True
 self.emit('query-changed', self._query)
 
 def __entry_changed_cb(self, entry):
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Maze: Remove KeepButton due to deprecation

2011-07-27 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

---
 olpcgames/activity.py |6 +-
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/olpcgames/activity.py b/olpcgames/activity.py
index 2149c30..77687cd 100644
--- a/olpcgames/activity.py
+++ b/olpcgames/activity.py
@@ -111,7 +111,7 @@ class PyGameActivity(activity.Activity):
 try:
 from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
 from sugar.activity.widgets import ActivityToolbarButton, 
StopButton, \
-ShareButton, KeepButton
+ShareButton
 from mybutton import MyActivityToolbarButton
 
 toolbar_box = ToolbarBox()
@@ -129,10 +129,6 @@ class PyGameActivity(activity.Activity):
 toolbar_box.toolbar.insert(share_button, -1)
 share_button.show()
 
-keep_button = KeepButton(self)
-toolbar_box.toolbar.insert(keep_button, -1)
-keep_button.show()
-
 stop_button = StopButton(self)
 toolbar_box.toolbar.insert(stop_button, -1)
 stop_button.show()
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Speak] Remove KeepButton due to deprecation

2011-07-27 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

---
 toolkit/activity_widgets.py |   24 +---
 1 files changed, 1 insertions(+), 23 deletions(-)

diff --git a/toolkit/activity_widgets.py b/toolkit/activity_widgets.py
index 50e2c6c..ce1007e 100644
--- a/toolkit/activity_widgets.py
+++ b/toolkit/activity_widgets.py
@@ -159,24 +159,6 @@ class ShareButton(RadioMenuButton):
 self.neighborhood.handler_unblock(self._neighborhood_handle)
 
 
-class KeepButton(ToolButton):
-
-def __init__(self, activity, **kwargs):
-ToolButton.__init__(self, **kwargs)
-self.props.tooltip = _('Keep')
-self.props.accelerator = 'CtrlS'
-
-color = profile.get_color()
-keep_icon = Icon(icon_name='document-save', xo_color=color)
-keep_icon.show()
-
-self.set_icon_widget(keep_icon)
-self.connect('clicked', self.__keep_button_clicked_cb, activity)
-
-def __keep_button_clicked_cb(self, button, activity):
-activity.copy()
-
-
 class TitleEntry(gtk.ToolItem):
 
 def __init__(self, activity, **kwargs):
@@ -222,7 +204,7 @@ class TitleEntry(gtk.ToolItem):
 
 class ActivityToolbar(gtk.Toolbar):
 The Activity toolbar with the Journal entry title, sharing,
-   Keep and Stop buttons
+   and Stop buttons
 
 All activities should have this toolbar. It is easiest to add it to your
 Activity by using the ActivityToolbox.
@@ -250,10 +232,6 @@ class ActivityToolbar(gtk.Toolbar):
 self.share.show()
 self.insert(self.share, -1)
 
-self.keep = KeepButton(activity)
-self.insert(self.keep, -1)
-self.keep.show()
-
 self.stop = StopButton(activity)
 self.insert(self.stop, -1)
 self.stop.show()
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Stopwatch] Remove KeepButton due to deprecation

2011-07-27 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

---
 activity.py |6 +-
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/activity.py b/activity.py
index 7a32a6d..88313e2 100644
--- a/activity.py
+++ b/activity.py
@@ -48,7 +48,7 @@ class StopWatchActivity(Activity):
 try:
 from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
 from sugar.activity.widgets import ActivityToolbarButton, 
StopButton, \
-ShareButton, KeepButton, TitleEntry, ActivityButton
+ShareButton, TitleEntry, ActivityButton
 except ImportError:
 OLD_TOOLBAR = True
 
@@ -70,10 +70,6 @@ class StopWatchActivity(Activity):
 toolbar_box.toolbar.insert(share_button, -1)
 share_button.show()
 
-keep_button = KeepButton(self)
-toolbar_box.toolbar.insert(keep_button, -1)
-keep_button.show()
-
 separator = gtk.SeparatorToolItem()
 separator.props.draw = False
 separator.set_expand(True)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Sugar-toolkit: Pack page in ToolbarButton when is conected to the window - OLPC #10930

2011-07-11 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

To initialize keybindings, the buttons in the toolbars need be attached
to the activity. This patch pack the page to the toolbarbutton when this is
added to the activity to enable the buttons keybindings initialization.
---
 src/sugar/graphics/toolbarbox.py |9 +
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/src/sugar/graphics/toolbarbox.py b/src/sugar/graphics/toolbarbox.py
index b674e8d..7e6023f 100644
--- a/src/sugar/graphics/toolbarbox.py
+++ b/src/sugar/graphics/toolbarbox.py
@@ -36,6 +36,15 @@ class ToolbarButton(ToolButton):
 self.connect('clicked',
 lambda widget: self.set_expanded(not self.is_expanded()))
 
+self.connect('hierarchy-changed', self._hierarchy_changed_cb)
+
+def _hierarchy_changed_cb(self, tool_button, previous_toplevel):
+if hasattr(self.parent, 'owner'):
+if self.page_widget:
+self._unparent()
+self.parent.owner.pack_start(self.page_widget)
+self.set_expanded(False)
+
 def get_toolbar_box(self):
 if not hasattr(self.parent, 'owner'):
 return None
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Write: Fix load of keybindings - OLPC #11049

2011-07-11 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Moved call to load of keybindings to map callback of activity
to delay the call, without this, when we open a new file
keybindings are not applied.
---
 AbiWordActivity.py |   17 ++---
 1 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/AbiWordActivity.py b/AbiWordActivity.py
index 06b9cf8..09543dd 100644
--- a/AbiWordActivity.py
+++ b/AbiWordActivity.py
@@ -169,6 +169,7 @@ class AbiWordActivity(activity.Activity):
 self.set_canvas(self.abiword_canvas)
 self.abiword_canvas.connect_after('map-event', self.__map_event_cb)
 self.abiword_canvas.show()
+self.connect_after('map-event', self.__map_activity_event_cb)
 
 self._zoom_handler = self.abiword_canvas.connect(zoom,
 self.__zoom_cb)
@@ -202,13 +203,6 @@ class AbiWordActivity(activity.Activity):
 def __map_event_cb(self, event, activity):
 logger.debug('__map_event_cb')
 
-# set custom keybindings for Write
-logger.debug('Loading keybindings')
-keybindings_file = os.path.join(get_bundle_path(), 'keybindings.xml')
-self.abiword_canvas.invoke_cmd(
-'com.abisource.abiword.loadbindings.fromURI',
-keybindings_file, 0, 0)
-
 # no ugly borders please
 self.abiword_canvas.set_property(shadow-type, gtk.SHADOW_NONE)
 
@@ -238,6 +232,15 @@ class AbiWordActivity(activity.Activity):
 # we are creating the activity
 logger.error(We are creating an activity)
 
+def __map_activity_event_cb(self, event, activity):
+# set custom keybindings for Write
+# we do it later because have problems if done before - OLPC #11049
+logger.error('Loading keybindings')
+keybindings_file = os.path.join(get_bundle_path(), 'keybindings.xml')
+self.abiword_canvas.invoke_cmd(
+'com.abisource.abiword.loadbindings.fromURI',
+keybindings_file, 0, 0)
+
 def get_preview(self):
 if not hasattr(self.abiword_canvas, 'render_page_to_image'):
 return activity.Activity.get_preview(self)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Update window title when the activity title changes - OLPC #10978

2011-07-06 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The patch updates the window title when the user changes
the title in the toolbar or in the Journal.

Signed-of-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar/activity/activity.py |   10 +-
 src/sugar/activity/widgets.py  |2 ++
 2 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py
index 31827da..35ad485 100644
--- a/src/sugar/activity/activity.py
+++ b/src/sugar/activity/activity.py
@@ -307,7 +307,8 @@ class Activity(Window, gtk.Container):
 if handle.object_id:
 self._jobject = datastore.get(handle.object_id)
 self.set_title(self._jobject.metadata['title'])
-
+self._jobject.metadata.connect('updated',
+   self.__jobject_updated_cb)
 if 'share-scope' in self._jobject.metadata:
 share_scope = self._jobject.metadata['share-scope']
 
@@ -333,6 +334,8 @@ class Activity(Window, gtk.Container):
 logging.debug('Creating a jobject.')
 self._jobject = self._initialize_journal_object()
 self.set_title(self._jobject.metadata['title'])
+self._jobject.metadata.connect('updated',
+   self.__jobject_updated_cb)
 
 def _initialize_journal_object(self):
 title = _('%s Activity') % get_bundle_name()
@@ -363,6 +366,11 @@ class Activity(Window, gtk.Container):
 
 return jobject
 
+def __jobject_updated_cb(self, jobject):
+if self.get_title() == jobject['title']:
+return
+self.set_title(jobject['title'])
+
 def _set_up_sharing(self, mesh_instance, share_scope):
 # handle activity share/join
 logging.debug('*** Act %s, mesh instance %r, scope %s',
diff --git a/src/sugar/activity/widgets.py b/src/sugar/activity/widgets.py
index 7166d3e..2cc863b 100644
--- a/src/sugar/activity/widgets.py
+++ b/src/sugar/activity/widgets.py
@@ -217,6 +217,8 @@ class TitleEntry(gtk.ToolItem):
 activity.metadata['title_set_by_user'] = '1'
 activity.save()
 
+activity.set_title(title)
+
 shared_activity = activity.get_shared_activity()
 if shared_activity is not None:
 shared_activity.props.name = title
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Sugar:Do not cache the activity tray palette - OLPC #10978

2011-07-06 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Needed to update the secondary text if the title in the activity changes.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/jarabe/frame/activitiestray.py |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/frame/activitiestray.py 
b/src/jarabe/frame/activitiestray.py
index 5445b49..2b5bf8d 100644
--- a/src/jarabe/frame/activitiestray.py
+++ b/src/jarabe/frame/activitiestray.py
@@ -54,6 +54,7 @@ class ActivityButton(RadioToolButton):
 RadioToolButton.__init__(self, group=group)
 
 self.set_palette_invoker(FrameWidgetInvoker(self))
+self.palette_invoker.cache_palette = False
 
 self._home_activity = home_activity
 self._notify_launch_hid = None
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Sugar-toolkit: Initialize window title with bundle name - OLPC #11037

2011-07-06 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

The activity tray palette compares the title with the bundle name
to check if a secondary text will be displayed.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
---
 src/sugar/activity/activity.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py
index 35ad485..a08bf03 100644
--- a/src/sugar/activity/activity.py
+++ b/src/sugar/activity/activity.py
@@ -275,7 +275,6 @@ class Activity(Window, gtk.Container):
 
 self.connect('realize', self.__realize_cb)
 self.connect('delete-event', self.__delete_event_cb)
-
 self._active = False
 self._activity_id = handle.activity_id
 self.shared_activity = None
@@ -304,6 +303,7 @@ class Activity(Window, gtk.Container):
 
 share_scope = SCOPE_PRIVATE
 
+self.set_title(get_bundle_name())
 if handle.object_id:
 self._jobject = datastore.get(handle.object_id)
 self.set_title(self._jobject.metadata['title'])
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Journal: Do not rescan external device if is not needed - OLPC #10841

2011-06-17 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org

Do not rescan if the created item is not part of the currently selected view
---
 src/jarabe/journal/listview.py |   10 +-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py
index 0aee1b7..1bc8f8a 100644
--- a/src/jarabe/journal/listview.py
+++ b/src/jarabe/journal/listview.py
@@ -118,7 +118,8 @@ class BaseListView(gtk.Bin):
 model.deleted.connect(self.__model_deleted_cb)
 
 def __model_created_cb(self, sender, **kwargs):
-self._set_dirty()
+if self._is_new_item_visible(kwargs):
+self._set_dirty()
 
 def __model_updated_cb(self, sender, **kwargs):
 self._set_dirty()
@@ -126,6 +127,13 @@ class BaseListView(gtk.Bin):
 def __model_deleted_cb(self, sender, **kwargs):
 self._set_dirty()
 
+def _is_new_item_visible(self, kwargs):
+Check if the created item is part of the currently selected view
+if self._query['mountpoints'] == ['/']:
+return not kwargs['object_id'].startswith('/')
+else:
+return 
kwargs['object_id'].startswith(self._query['mountpoints'][0])
+
 def _add_columns(self):
 cell_favorite = CellRendererFavorite(self.tree_view)
 cell_favorite.connect('clicked', self.__favorite_clicked_cb)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Browse: Set and restore index in the history - Fix OLPC #10779 / SL #2499

2011-06-08 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

If the user go back, or select any page in the history and
close the activity, need restore at the next start, the history,
and the index in the history too.
---
 browser.py |7 ++-
 webactivity.py |   26 ++
 webtoolbar.py  |1 +
 3 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/browser.py b/browser.py
index b9c1f69..3cef766 100644
--- a/browser.py
+++ b/browser.py
@@ -281,7 +281,6 @@ class Browser(WebView):
 
 def do_setup(self):
 WebView.do_setup(self)
-
 listener = xpcom.server.WrapObject(ContentInvoker(self),
interfaces.nsIDOMEventListener)
 self.window_root.addEventListener('click', listener, False)
@@ -351,6 +350,12 @@ class Browser(WebView):
 interfaces.nsIMarkupDocumentViewer)
 markupDocumentViewer.fullZoom -= _ZOOM_AMOUNT
 
+def get_history_index(self):
+return self.web_navigation.sessionHistory.index
+
+def set_history_index(self, index):
+self.web_navigation.gotoIndex(index)
+
 
 class PopupDialog(gtk.Window):
 def __init__(self):
diff --git a/webactivity.py b/webactivity.py
index 48cb3ed..8ad95a6 100644
--- a/webactivity.py
+++ b/webactivity.py
@@ -458,6 +458,10 @@ class WebActivity(activity.Activity):
   link['owner'], -1, link['hash'])
 logging.debug('## reading %s', data)
 self._tabbed_view.set_session(self.model.data['history'])
+for number, tab in enumerate(self.model.data['currents']):
+browser = self._tabbed_view.get_nth_page(number)
+browser.set_history_index(tab['history_index'])
+
 self._tabbed_view.set_current_page(self.model.data['current_tab'])
 elif self.metadata['mime_type'] == 'text/uri-list':
 data = self._get_data_from_file_path(file_path)
@@ -469,19 +473,6 @@ class WebActivity(activity.Activity):
   'list of multiple uris by now.')
 else:
 self._tabbed_view.props.current_browser.load_uri(file_path)
-self._load_urls()
-
-def _load_urls(self):
-if self.model.data['currents'] != None:
-first = True
-for current_tab in self.model.data['currents']:
-if first:
-browser = self._tabbed_view.current_browser
-first = False
-else:
-browser = Browser()
-self._tabbed_view._append_tab(browser)
-browser.load_uri(current_tab['url'])
 
 def write_file(self, file_path):
 if not self.metadata['mime_type']:
@@ -503,9 +494,12 @@ class WebActivity(activity.Activity):
 for n in range(0, self._tabbed_view.get_n_pages()):
 n_browser = self._tabbed_view.get_nth_page(n)
 if n_browser != None:
-nsiuri = browser.progress.location
-ui_uri = browser.get_url_from_nsiuri(nsiuri)
-info = {'title': browser.props.title, 'url': ui_uri}
+nsiuri = n_browser.progress.location
+ui_uri = n_browser.get_url_from_nsiuri(nsiuri)
+history_index = n_browser.get_history_index()
+info = {'title': n_browser.props.title, 'url': ui_uri,
+'history_index': history_index}
+
 self.model.data['currents'].append(info)
 
 f = open(file_path, 'w')
diff --git a/webtoolbar.py b/webtoolbar.py
index 8b0e108..6cb3ee7 100644
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -355,6 +355,7 @@ class PrimaryToolbar(ToolbarBase):
 self._history = browser.history
 self._session_history_changed_hid = self._history.connect(
 'session-history-changed', self._session_history_changed_cb)
+self._reload_session_history()
 
 if self._browser is not None:
 self._browser.disconnect(self._title_changed_hid)
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Browse: Set and restore index in the history - Fix OLPC #10779

2011-06-06 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

If the user go back, or select any page in the history and
close the activity, need restore at the next start, the history,
and the index in the history too.
---
 browser.py |6 ++
 webactivity.py |   24 ++--
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/browser.py b/browser.py
index b9c1f69..9bb7a1b 100644
--- a/browser.py
+++ b/browser.py
@@ -351,6 +351,12 @@ class Browser(WebView):
 interfaces.nsIMarkupDocumentViewer)
 markupDocumentViewer.fullZoom -= _ZOOM_AMOUNT
 
+def get_history_index(self):
+return self.web_navigation.sessionHistory.index
+
+def set_history_index(self, index):
+self.web_navigation.gotoIndex(index)
+
 
 class PopupDialog(gtk.Window):
 def __init__(self):
diff --git a/webactivity.py b/webactivity.py
index 48cb3ed..8619144 100644
--- a/webactivity.py
+++ b/webactivity.py
@@ -458,6 +458,12 @@ class WebActivity(activity.Activity):
   link['owner'], -1, link['hash'])
 logging.debug('## reading %s', data)
 self._tabbed_view.set_session(self.model.data['history'])
+tab_number = 0
+for current in self.model.data['currents']:
+browser = self._tabbed_view.get_nth_page(tab_number)
+browser.set_history_index(current['index'])
+tab_number = tab_number + 1
+
 self._tabbed_view.set_current_page(self.model.data['current_tab'])
 elif self.metadata['mime_type'] == 'text/uri-list':
 data = self._get_data_from_file_path(file_path)
@@ -469,19 +475,6 @@ class WebActivity(activity.Activity):
   'list of multiple uris by now.')
 else:
 self._tabbed_view.props.current_browser.load_uri(file_path)
-self._load_urls()
-
-def _load_urls(self):
-if self.model.data['currents'] != None:
-first = True
-for current_tab in self.model.data['currents']:
-if first:
-browser = self._tabbed_view.current_browser
-first = False
-else:
-browser = Browser()
-self._tabbed_view._append_tab(browser)
-browser.load_uri(current_tab['url'])
 
 def write_file(self, file_path):
 if not self.metadata['mime_type']:
@@ -505,7 +498,10 @@ class WebActivity(activity.Activity):
 if n_browser != None:
 nsiuri = browser.progress.location
 ui_uri = browser.get_url_from_nsiuri(nsiuri)
-info = {'title': browser.props.title, 'url': ui_uri}
+index = browser.get_history_index()
+info = {'title': browser.props.title, 'url': ui_uri,
+'index': index}
+
 self.model.data['currents'].append(info)
 
 f = open(file_path, 'w')
-- 
1.7.4.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Add alpha and scale functionality to the icon, can be used in the launcher to do the animation - v2

2011-03-23 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
Acked-By: Simon Schampijer si...@laptop.org
---
 src/sugar/graphics/icon.py |   50 ---
 1 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/src/sugar/graphics/icon.py b/src/sugar/graphics/icon.py
index 870c49e..7d84f2b 100644
--- a/src/sugar/graphics/icon.py
+++ b/src/sugar/graphics/icon.py
@@ -332,6 +332,8 @@ class Icon(gtk.Image):
 # collected while it's still used if it's a sugar.util.TempFilePath.
 # See #1175
 self._file = None
+self._alpha = 1.0
+self._scale = 1.0
 
 gobject.GObject.__init__(self, **kwargs)
 
@@ -420,8 +422,22 @@ class Icon(gtk.Image):
 (allocation.height - requisition[1]) * yalign)
 
 cr = self.window.cairo_create()
+
+if self._scale != 1.0:
+cr.scale(self._scale, self._scale)
+
+margin = self._buffer.width * (1 - self._scale) / 2
+x, y = x + margin, y + margin
+
+x = x / self._scale
+y = y / self._scale
+
 cr.set_source_surface(surface, x, y)
-cr.paint()
+
+if self._alpha == 1.0:
+cr.paint()
+else:
+cr.paint_with_alpha(self._alpha)
 
 def set_xo_color(self, value):
 
@@ -524,6 +540,22 @@ class Icon(gtk.Image):
 badge_name = gobject.property(
 type=str, getter=get_badge_name, setter=set_badge_name)
 
+def set_alpha(self, value):
+if self._alpha != value:
+self._alpha = value
+self.queue_draw()
+
+alpha = gobject.property(
+type=float, setter=set_alpha)
+
+def set_scale(self, value):
+if self._scale != value:
+self._scale = value
+self.queue_draw()
+
+scale = gobject.property(
+type=float, setter=set_scale)
+
 
 class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 
@@ -534,6 +566,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 
 self._buffer = _IconBuffer()
 self._palette_invoker = CanvasInvoker()
+self._alpha = 1.0
 
 hippo.CanvasBox.__init__(self, **kwargs)
 
@@ -775,8 +808,6 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 None
 
 
-logging.warning(
-'CanvasIcon: the scale parameter is currently unsupported')
 if self._buffer.scale != value:
 self._buffer.scale = value
 self.emit_request_changed()
@@ -797,6 +828,14 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 scale = gobject.property(
 type=float, getter=get_scale, setter=set_scale)
 
+def set_alpha(self, alpha):
+if self._alpha != alpha:
+self._alpha = alpha
+self.emit_paint_needed(0, 0, -1, -1)
+
+alpha = gobject.property(
+type=float, setter=set_alpha)
+
 def set_cache(self, value):
 
 Parameters
@@ -878,7 +917,10 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 y = (height - surface.get_height()) / 2
 
 cr.set_source_surface(surface, x, y)
-cr.paint()
+if self._alpha == 1.0:
+cr.paint()
+else:
+cr.paint_with_alpha(self._alpha)
 
 def do_get_content_width_request(self):
 
-- 
1.7.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Do startup animation of the activity icon using scaling and alpha - v2

2011-03-23 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This render the SVG image only one time, and then use alpha and scaling
of the rendered icon and will speed up the overall activity startup.
Another side effect is that the ticket #2080 effects are reduced greatly.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
Acked-By: Simon Schampijer si...@laptop.org
---
 src/jarabe/view/launcher.py|   83 +--
 src/jarabe/view/pulsingicon.py |   82 ++-
 2 files changed, 65 insertions(+), 100 deletions(-)

diff --git a/src/jarabe/view/launcher.py b/src/jarabe/view/launcher.py
index 89251e5..7437d21 100644
--- a/src/jarabe/view/launcher.py
+++ b/src/jarabe/view/launcher.py
@@ -18,16 +18,13 @@ import logging
 from gettext import gettext as _
 
 import gtk
-import hippo
 import gobject
 
 from sugar import wm
 from sugar.graphics import style
-from sugar.graphics import animator
-from sugar.graphics.xocolor import XoColor
 
 from jarabe.model import shell
-from jarabe.view.pulsingicon import CanvasPulsingIcon
+from jarabe.view.pulsingicon import PulsingIcon
 
 
 class LaunchWindow(gtk.Window):
@@ -51,12 +48,15 @@ class LaunchWindow(gtk.Window):
 canvas.pack_start(header, expand=False)
 
 self._activity_id = activity_id
-self._box = LaunchBox(activity_id, icon_path, icon_color)
-box = hippo.Canvas()
-box.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color())
-box.set_root(self._box)
-box.show()
-canvas.pack_start(box)
+
+self._activity_icon = PulsingIcon(file=icon_path,
+  pixel_size=style.XLARGE_ICON_SIZE)
+self._activity_icon.set_base_color(icon_color)
+self._activity_icon.set_zooming_properties(style.SMALL_ICON_SIZE,
+   style.XLARGE_ICON_SIZE, 10)
+self._activity_icon.set_pulsing(True)
+self._activity_icon.show()
+canvas.pack_start(self._activity_icon)
 
 footer = gtk.VBox(spacing=style.DEFAULT_SPACING)
 footer.set_size_request(-1, bar_size)
@@ -78,11 +78,16 @@ class LaunchWindow(gtk.Window):
 screen = gtk.gdk.screen_get_default()
 screen.connect('size-changed', self.__size_changed_cb)
 
+self._home = shell.get_model()
+self._home.connect('active-activity-changed',
+   self.__active_activity_changed_cb)
+
+self.connect('destroy', self.__destroy_cb)
+
 self._update_size()
 
 def show(self):
 self.present()
-self._box.zoom_in()
 
 def _update_size(self):
 self.resize(gtk.gdk.screen_width(), gtk.gdk.screen_height())
@@ -95,65 +100,15 @@ class LaunchWindow(gtk.Window):
 def __size_changed_cb(self, screen):
 self._update_size()
 
-
-class LaunchBox(hippo.CanvasBox):
-
-def __init__(self, activity_id, icon_path, icon_color):
-gobject.GObject.__init__(self, orientation=hippo.ORIENTATION_VERTICAL)
-
-self._activity_id = activity_id
-self._activity_icon = CanvasPulsingIcon(
-file_name=icon_path,
-pulse_color=icon_color,
-background_color=style.COLOR_WHITE.get_gdk_color())
-self.append(self._activity_icon, hippo.PACK_EXPAND)
-
-# FIXME support non-xo colors in CanvasPulsingIcon
-self._activity_icon.props.base_color = \
-XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
-   style.COLOR_TRANSPARENT.get_svg()))
-
-self._animator = animator.Animator(1.0)
-
-self._home = shell.get_model()
-self._home.connect('active-activity-changed',
-   self.__active_activity_changed_cb)
-
-self.connect('destroy', self.__destroy_cb)
-
-def __destroy_cb(self, box):
-self._activity_icon.props.pulsing = False
-self._home.disconnect_by_func(self.__active_activity_changed_cb)
-
-def zoom_in(self):
-self._activity_icon.props.size = style.STANDARD_ICON_SIZE
-
-self._animator.remove_all()
-self._animator.add(_Animation(self._activity_icon,
-  style.STANDARD_ICON_SIZE,
-  style.XLARGE_ICON_SIZE))
-self._animator.start()
-self._activity_icon.props.pulsing = True
-
 def __active_activity_changed_cb(self, model, activity):
 if activity.get_activity_id() == self._activity_id:
 self._activity_icon.props.paused = False
 else:
 self._activity_icon.props.paused = True
 
-
-class _Animation(animator.Animation):
-
-def __init__(self, icon, start_size, end_size):
-animator.Animation.__init__(self, 0.0, 1.0)
-
-self._icon = icon
-self.start_size = start_size
-self.end_size = end_size
-
-def next_frame(self, current):
-d = (self.end_size - 

[Sugar-devel] [PATCH] Add alpha and scale functionality to the icon, can be used in the launcher to do the animation

2011-03-04 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
Acked-By: Simon Schampijer si...@laptop.org
---
 src/sugar/graphics/icon.py |   45 +--
 1 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/src/sugar/graphics/icon.py b/src/sugar/graphics/icon.py
index 870c49e..72254b6 100644
--- a/src/sugar/graphics/icon.py
+++ b/src/sugar/graphics/icon.py
@@ -332,6 +332,8 @@ class Icon(gtk.Image):
 # collected while it's still used if it's a sugar.util.TempFilePath.
 # See #1175
 self._file = None
+self._alpha = 1.0
+self._scale = 1.0
 
 gobject.GObject.__init__(self, **kwargs)
 
@@ -420,8 +422,22 @@ class Icon(gtk.Image):
 (allocation.height - requisition[1]) * yalign)
 
 cr = self.window.cairo_create()
+
+if self._scale != 1.0:
+cr.scale(self._scale, self._scale)
+
+margin = self._buffer.width * (1 - self._scale) / 2
+x, y = x + margin, y + margin
+
+x = x / self._scale
+y = y / self._scale
+
 cr.set_source_surface(surface, x, y)
-cr.paint()
+
+if self._alpha == 1.0:
+cr.paint()
+else:
+cr.paint_with_alpha(self._alpha)
 
 def set_xo_color(self, value):
 
@@ -524,6 +540,22 @@ class Icon(gtk.Image):
 badge_name = gobject.property(
 type=str, getter=get_badge_name, setter=set_badge_name)
 
+def set_alpha(self, value):
+if self._alpha != value:
+self._alpha = value
+self.queue_draw()
+
+alpha = gobject.property(
+type=float, setter=set_alpha)
+
+def set_scale(self, value):
+if self._scale != value:
+self._scale = value
+self.queue_draw()
+
+scale = gobject.property(
+type=float, setter=set_scale)
+
 
 class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 
@@ -534,6 +566,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 
 self._buffer = _IconBuffer()
 self._palette_invoker = CanvasInvoker()
+self._alpha = 1.0
 
 hippo.CanvasBox.__init__(self, **kwargs)
 
@@ -775,8 +808,6 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 None
 
 
-logging.warning(
-'CanvasIcon: the scale parameter is currently unsupported')
 if self._buffer.scale != value:
 self._buffer.scale = value
 self.emit_request_changed()
@@ -797,6 +828,14 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
 scale = gobject.property(
 type=float, getter=get_scale, setter=set_scale)
 
+def set_alpha(self, alpha):
+if self._alpha != alpha:
+self._alpha = alpha
+self.emit_request_changed()
+
+alpha = gobject.property(
+type=float, setter=set_alpha)
+
 def set_cache(self, value):
 
 Parameters
-- 
1.7.4

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Do startup animation of the activity icon using scaling and alpha

2011-03-04 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

This render the SVG image only one time, and then use alpha and scaling
of the rendered icon and will speed up the overall activity startup.
Another side effect is that the ticket #2080 effects are reduced greatly.

Signed-off-by: Gonzalo Odiard gonz...@laptop.org
Acked-By: Simon Schampijer si...@laptop.org
---
 src/jarabe/view/launcher.py|   83 +--
 src/jarabe/view/pulsingicon.py |   80 +-
 2 files changed, 64 insertions(+), 99 deletions(-)

diff --git a/src/jarabe/view/launcher.py b/src/jarabe/view/launcher.py
index 89251e5..7437d21 100644
--- a/src/jarabe/view/launcher.py
+++ b/src/jarabe/view/launcher.py
@@ -18,16 +18,13 @@ import logging
 from gettext import gettext as _
 
 import gtk
-import hippo
 import gobject
 
 from sugar import wm
 from sugar.graphics import style
-from sugar.graphics import animator
-from sugar.graphics.xocolor import XoColor
 
 from jarabe.model import shell
-from jarabe.view.pulsingicon import CanvasPulsingIcon
+from jarabe.view.pulsingicon import PulsingIcon
 
 
 class LaunchWindow(gtk.Window):
@@ -51,12 +48,15 @@ class LaunchWindow(gtk.Window):
 canvas.pack_start(header, expand=False)
 
 self._activity_id = activity_id
-self._box = LaunchBox(activity_id, icon_path, icon_color)
-box = hippo.Canvas()
-box.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color())
-box.set_root(self._box)
-box.show()
-canvas.pack_start(box)
+
+self._activity_icon = PulsingIcon(file=icon_path,
+  pixel_size=style.XLARGE_ICON_SIZE)
+self._activity_icon.set_base_color(icon_color)
+self._activity_icon.set_zooming_properties(style.SMALL_ICON_SIZE,
+   style.XLARGE_ICON_SIZE, 10)
+self._activity_icon.set_pulsing(True)
+self._activity_icon.show()
+canvas.pack_start(self._activity_icon)
 
 footer = gtk.VBox(spacing=style.DEFAULT_SPACING)
 footer.set_size_request(-1, bar_size)
@@ -78,11 +78,16 @@ class LaunchWindow(gtk.Window):
 screen = gtk.gdk.screen_get_default()
 screen.connect('size-changed', self.__size_changed_cb)
 
+self._home = shell.get_model()
+self._home.connect('active-activity-changed',
+   self.__active_activity_changed_cb)
+
+self.connect('destroy', self.__destroy_cb)
+
 self._update_size()
 
 def show(self):
 self.present()
-self._box.zoom_in()
 
 def _update_size(self):
 self.resize(gtk.gdk.screen_width(), gtk.gdk.screen_height())
@@ -95,65 +100,15 @@ class LaunchWindow(gtk.Window):
 def __size_changed_cb(self, screen):
 self._update_size()
 
-
-class LaunchBox(hippo.CanvasBox):
-
-def __init__(self, activity_id, icon_path, icon_color):
-gobject.GObject.__init__(self, orientation=hippo.ORIENTATION_VERTICAL)
-
-self._activity_id = activity_id
-self._activity_icon = CanvasPulsingIcon(
-file_name=icon_path,
-pulse_color=icon_color,
-background_color=style.COLOR_WHITE.get_gdk_color())
-self.append(self._activity_icon, hippo.PACK_EXPAND)
-
-# FIXME support non-xo colors in CanvasPulsingIcon
-self._activity_icon.props.base_color = \
-XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
-   style.COLOR_TRANSPARENT.get_svg()))
-
-self._animator = animator.Animator(1.0)
-
-self._home = shell.get_model()
-self._home.connect('active-activity-changed',
-   self.__active_activity_changed_cb)
-
-self.connect('destroy', self.__destroy_cb)
-
-def __destroy_cb(self, box):
-self._activity_icon.props.pulsing = False
-self._home.disconnect_by_func(self.__active_activity_changed_cb)
-
-def zoom_in(self):
-self._activity_icon.props.size = style.STANDARD_ICON_SIZE
-
-self._animator.remove_all()
-self._animator.add(_Animation(self._activity_icon,
-  style.STANDARD_ICON_SIZE,
-  style.XLARGE_ICON_SIZE))
-self._animator.start()
-self._activity_icon.props.pulsing = True
-
 def __active_activity_changed_cb(self, model, activity):
 if activity.get_activity_id() == self._activity_id:
 self._activity_icon.props.paused = False
 else:
 self._activity_icon.props.paused = True
 
-
-class _Animation(animator.Animation):
-
-def __init__(self, icon, start_size, end_size):
-animator.Animation.__init__(self, 0.0, 1.0)
-
-self._icon = icon
-self.start_size = start_size
-self.end_size = end_size
-
-def next_frame(self, current):
-d = (self.end_size - self.start_size) 

[Sugar-devel] [PATCH] Copying files multiple times results in bogus names. (SL#2060)

2010-11-23 Thread godiard
From: Gonzalo Odiard godi...@gmail.com

---
 src/jarabe/journal/model.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py
index 81ca7d4..81d1663 100644
--- a/src/jarabe/journal/model.py
+++ b/src/jarabe/journal/model.py
@@ -529,8 +529,8 @@ def _get_file_name(title, mime_type):
 def _get_unique_file_name(mount_point, file_name):
 if os.path.exists(os.path.join(mount_point, file_name)):
 i = 1
+name, extension = os.path.splitext(file_name)
 while len(file_name) = 255:
-name, extension = os.path.splitext(file_name)
 file_name = name + '_' + str(i) + extension
 if not os.path.exists(os.path.join(mount_point, file_name)):
 break
-- 
1.7.1.1

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] OLPC #8857 - Browse fails to download some files with non-ascii characters

2010-11-18 Thread godiard
From: Gonzalo Odiard godi...@sugarlabs.org

Browse can't download a file if the name is encoded in a codec different to 
UTF-8
---
 downloadmanager.py |8 ++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/downloadmanager.py b/downloadmanager.py
index c396317..90d22a5 100644
--- a/downloadmanager.py
+++ b/downloadmanager.py
@@ -306,9 +306,13 @@ class Download:
 elif self._source.scheme == 'data':
 return 'Data URI'
 else:
-path = urlparse.urlparse(self._source.spec).path
+uri = self._source
+if uri == None:
+return ''
+cls = components.classes['@mozilla.org/intl/texttosuburi;1']
+texttosuburi = cls.getService(interfaces.nsITextToSubURI)
+path = texttosuburi.unEscapeURIForUI(uri.originCharset, uri.spec)
 location, file_name = os.path.split(path)
-file_name = urllib.unquote(file_name.encode('utf-8', 'replace'))
 return file_name
 
 def _create_journal_object(self):
-- 
1.7.2.3

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH] Write: Cleanup sharing code

2010-11-04 Thread godiard
From: Gonzalo Odiard godi...@sugarlabs.org

Updated and applied patch from tickets OLPC #8680
Related to tickets SL #1962 and OLPC #5062
---
 AbiWordActivity.py |  219 +++-
 1 files changed, 79 insertions(+), 140 deletions(-)

diff --git a/AbiWordActivity.py b/AbiWordActivity.py
index fda1fdf..7717e55 100644
--- a/AbiWordActivity.py
+++ b/AbiWordActivity.py
@@ -24,7 +24,6 @@ import os
 import gobject
 gobject.threads_init()
 
-import dbus
 import gtk
 import telepathy
 import telepathy.client
@@ -36,7 +35,6 @@ from sugar.activity.widgets import StopButton
 from sugar.activity.widgets import ActivityToolbarButton
 from sugar.activity.activity import get_bundle_path
 
-from sugar.presence import presenceservice
 from sugar import mime
 
 from sugar.graphics.toolbarbox import ToolbarButton, ToolbarBox
@@ -221,19 +219,13 @@ class AbiWordActivity(activity.Activity):
 
 # activity sharing
 self.participants = {}
-pservice = presenceservice.get_instance()
-
-bus = dbus.Bus()
-name, path = pservice.get_preferred_connection()
-self.conn = telepathy.client.Connection(name, path)
-self.initiating = None
 self.joined = False
 
 self.connect('shared', self._shared_cb)
 
 if self._shared_activity:
 # we are joining the activity
-logger.debug('We are joining an activity')
+logger.error('We are joining an activity')
 self.connect('joined', self._joined_cb)
 self._shared_activity.connect('buddy-joined',
 self._buddy_joined_cb)
@@ -243,9 +235,7 @@ class AbiWordActivity(activity.Activity):
 self._joined_cb()
 else:
 # we are creating the activity
-logger.debug(We are creating an activity)
-
-owner = pservice.get_owner()
+logger.error(We are creating an activity)
 
 def get_preview(self):
 if not hasattr(self.abiword_canvas, 'render_page_to_image'):
@@ -266,68 +256,30 @@ class AbiWordActivity(activity.Activity):
 return preview_data
 
 def _shared_cb(self, activity):
-logger.debug('My Write activity was shared')
-self.initiating = True
-self._setup()
+logger.error('My Write activity was shared')
+self._sharing_setup()
 
 self._shared_activity.connect('buddy-joined', self._buddy_joined_cb)
 self._shared_activity.connect('buddy-left', self._buddy_left_cb)
 
 channel = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES]
-logger.debug('This is my activity: offering a tube...')
+logger.error('This is my activity: offering a tube...')
 id = channel.OfferDBusTube('com.abisource.abiword.abicollab', {})
-logger.debug('Tube address: %s', channel.GetDBusTubeAddress(id))
+logger.error('Tube address: %s', channel.GetDBusTubeAddress(id))
 
-def _setup(self):
-logger.debug(_setup())
+def _sharing_setup(self):
+logger.debug(_sharing_setup())
 
 if self._shared_activity is None:
 logger.error('Failed to share or join activity')
 return
 
-bus_name, conn_path, channel_paths = \
-self._shared_activity.get_channels()
-
-# Work out what our room is called and whether we have Tubes already
-room = None
-tubes_chan = None
-text_chan = None
-for channel_path in channel_paths:
-channel = telepathy.client.Channel(bus_name, channel_path)
-htype, handle = channel.GetHandle()
-if htype == telepathy.HANDLE_TYPE_ROOM:
-logger.debug('Found our room: it has handle#%d %s',
-handle, self.conn.InspectHandles(htype, [handle])[0])
-room = handle
-ctype = channel.GetChannelType()
-if ctype == telepathy.CHANNEL_TYPE_TUBES:
-logger.debug('Found our Tubes channel at %s', channel_path)
-tubes_chan = channel
-elif ctype == telepathy.CHANNEL_TYPE_TEXT:
-logger.debug('Found our Text channel at %s', channel_path)
-text_chan = channel
-
-if room is None:
-logger.error(Presence service didn't create a room)
-return
-if text_chan is None:
-logger.error(Presence service didn't create a text channel)
-return
-
-# Make sure we have a Tubes channel - PS doesn't yet provide one
-if tubes_chan is None:
-logger.debug('Didn''t find our Tubes negotation channel, ' +
-'requesting one...')
-tubes_chan = self.conn.request_channel( \
-telepathy.CHANNEL_TYPE_TUBES, \
-telepathy.HANDLE_TYPE_ROOM, room, True)
-logger.debug('Got our tubes negotiation channel')
-
-self.tubes_chan = 

[Sugar-devel] [PATCH Write] Change the logic for preserve the mime type at reading and saving files

2010-11-03 Thread godiard
From: Gonzalo Odiard godi...@sugarlabs.org

Open the text files in plain/text format, save the new file like .odt files
and preserve the mime type in all the cases but .doc files (abiword saves them 
like .rtf)
Related to tickets SL #2127, OLPC #8972, OLPC #5291 and OLPC #1925
---
 AbiWordActivity.py |   40 +---
 1 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/AbiWordActivity.py b/AbiWordActivity.py
index 0f62523..fda1fdf 100644
--- a/AbiWordActivity.py
+++ b/AbiWordActivity.py
@@ -37,6 +37,7 @@ from sugar.activity.widgets import ActivityToolbarButton
 from sugar.activity.activity import get_bundle_path
 
 from sugar.presence import presenceservice
+from sugar import mime
 
 from sugar.graphics.toolbarbox import ToolbarButton, ToolbarBox
 from sugar.graphics.toggletoolbutton import ToggleToolButton
@@ -459,8 +460,8 @@ class AbiWordActivity(activity.Activity):
 def read_file(self, file_path):
 logging.debug('AbiWordActivity.read_file: %s, mimetype: %s',
 file_path, self.metadata['mime_type'])
-if 'source' in self.metadata and self.metadata['source'] == '1':
-logger.debug('Opening file in view source mode')
+if self.metadata['mime_type'] in ['text/plain', 'text/csv'] or \
+   'text/plain' in mime.get_mime_parents(self.metadata['mime_type']):
 self.abiword_canvas.load_file('file://' + file_path, 'text/plain')
 else:
 # we pass no mime/file type, let libabiword autodetect it,
@@ -468,25 +469,26 @@ class AbiWordActivity(activity.Activity):
 self.abiword_canvas.load_file('file://' + file_path, '')
 
 def write_file(self, file_path):
-logging.debug('AbiWordActivity.write_file')
-
-# check if we have a default mimetype; if not,
-# fall back to OpenDocument
-# also fallback if we know we cannot export in that format
-if 'mime_type' not in self.metadata or \
-self.metadata['mime_type'] == '' or \
-self.metadata['mime_type'] == 'application/msword':
-self.metadata['mime_type'] = \
-'application/vnd.oasis.opendocument.text'
-
-# if we were viewing the source of a file,
-# then always save as plain text
-actual_mimetype = self.metadata['mime_type']
-if 'source' in self.metadata and self.metadata['source'] == '1':
+logging.debug('AbiWordActivity.write_file: %s, mimetype: %s',
+file_path, self.metadata['mime_type'])
+# if we were editing a text file save as plain text
+if self.metadata['mime_type'] in ['text/plain', 'text/csv'] or \
+   'text/plain' in mime.get_mime_parents(self.metadata['mime_type']):
 logger.debug('Writing file as type source (text/plain)')
-actual_mimetype = 'text/plain'
+self.abiword_canvas.save('file://' + file_path, 'text/plain', '')
+else:
+#if the file is new, save in .odt format
+if self.metadata['mime_type'] == '':
+self.metadata['mime_type'] = \
+'application/vnd.oasis.opendocument.text'
+
+# Abiword can't save in .doc format, save in .rtf instead
+if self.metadata['mime_type'] == 'application/msword':
+self.metadata['mime_type'] = 'application/rtf'
+
+self.abiword_canvas.save('file://' + file_path,
+self.metadata['mime_type'], '')
 
 self.metadata['fulltext'] = \
 self.abiword_canvas.get_content(extension_or_mimetype=.txt) \
 [:3000]
-self.abiword_canvas.save('file://' + file_path, actual_mimetype, '')
-- 
1.7.2.3

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


[Sugar-devel] [PATCH Pippy] Add EditToolbar and modify toolbars to support the older from sugar 0.86

2010-11-02 Thread godiard
From: Gonzalo Odiard godi...@sugarlabs.org

---
 groupthink/sugar_tools.py |   23 +---
 pippy_app.py  |   87 +++--
 2 files changed, 94 insertions(+), 16 deletions(-)

diff --git a/groupthink/sugar_tools.py b/groupthink/sugar_tools.py
index 0292a0b..66d4a0e 100644
--- a/groupthink/sugar_tools.py
+++ b/groupthink/sugar_tools.py
@@ -28,6 +28,13 @@ import gobject
 
 import groupthink_base as groupthink
 
+OLD_TOOLBAR = False
+try:
+from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
+from sugar.activity.widgets import ActivityToolbarButton
+except ImportError:
+OLD_TOOLBAR = True
+
 def exhaust_event_loop():
 while gtk.events_pending():
 gtk.main_iteration()
@@ -69,11 +76,17 @@ class GroupActivity(Activity):
 else:
 self.message = self.message_preparing
 
-# top toolbar with share and close buttons:
-toolbox = ActivityToolbox(self)
-self.set_toolbox(toolbox)
-toolbox.show()
-
+if OLD_TOOLBAR:
+self.toolbox = ActivityToolbox(self)
+self.set_toolbox(self.toolbox)
+self.toolbox.show()
+self.set_toolbox(self.toolbox)
+else:
+toolbar_box = ToolbarBox()
+self.activity_button = ActivityToolbarButton(self)
+toolbar_box.toolbar.insert(self.activity_button, 0)
+self.set_toolbar_box(toolbar_box)
+
 v = gtk.VBox()
 self.startup_label = gtk.Label(self.message)
 v.pack_start(self.startup_label)
diff --git a/pippy_app.py b/pippy_app.py
index fc8..636c52d 100644
--- a/pippy_app.py
+++ b/pippy_app.py
@@ -30,9 +30,10 @@ from port.style import font_zoom
 from signal import SIGTERM
 from gettext import gettext as _
 
+from sugar.activity import activity
 from activity import ViewSourceActivity, TARGET_TYPE_TEXT
 from sugar.activity.activity import ActivityToolbox, \
- get_bundle_path, get_bundle_name
+ EditToolbar, get_bundle_path, get_bundle_name
 from sugar.graphics import style
 from sugar.graphics.toolbutton import ToolButton
 
@@ -45,6 +46,13 @@ PYTHON_PREFIX=#!/usr/bin/python
 # -*- coding: utf-8 -*-
 
 
+OLD_TOOLBAR = False
+try:
+from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
+from sugar.activity.widgets import StopButton
+except ImportError:
+OLD_TOOLBAR = True
+
 # get screen sizes
 SIZE_X = gtk.gdk.screen_width()
 SIZE_Y = gtk.gdk.screen_height()
@@ -62,10 +70,14 @@ class PippyActivity(ViewSourceActivity, 
groupthink.sugar_tools.GroupActivity):
 self._logger = logging.getLogger('pippy-activity')
 
 # Top toolbar with share and close buttons:
-toolbox = ActivityToolbox(self)
-activity_toolbar = toolbox.get_activity_toolbar()
+
+if OLD_TOOLBAR:
+activity_toolbar = self.toolbox.get_activity_toolbar()
+else:
+activity_toolbar = self.activity_button.page
+
 # add 'make bundle' entry to 'keep' palette.
-palette = toolbox.get_activity_toolbar().keep.get_palette()
+palette = activity_toolbar.keep.get_palette()
 # XXX: should clear out old palette entries?
 from sugar.graphics.menuitem import MenuItem
 from sugar.graphics.icon import Icon
@@ -80,6 +92,32 @@ class PippyActivity(ViewSourceActivity, 
groupthink.sugar_tools.GroupActivity):
 palette.menu.append(menu_item)
 menu_item.show()
 
+self._edit_toolbar = activity.EditToolbar()
+
+if OLD_TOOLBAR:
+activity_toolbar = gtk.Toolbar()
+self.toolbox.add_toolbar('Pippy', activity_toolbar)
+self.toolbox.set_current_toolbar(1)
+self.toolbox.add_toolbar(_('Edit'), self._edit_toolbar)
+else:
+edit_toolbar_button = ToolbarButton()
+edit_toolbar_button.set_page(self._edit_toolbar)
+edit_toolbar_button.props.icon_name = 'toolbar-edit'
+edit_toolbar_button.props.label = _('Edit')
+self.get_toolbar_box().toolbar.insert(edit_toolbar_button, -1)
+
+self._edit_toolbar.show()
+
+self._edit_toolbar.undo.connect('clicked', self.__undobutton_cb)
+self._edit_toolbar.redo.connect('clicked', self.__redobutton_cb)
+self._edit_toolbar.copy.connect('clicked', self.__copybutton_cb)
+self._edit_toolbar.paste.connect('clicked', self.__pastebutton_cb)
+
+if OLD_TOOLBAR:
+pippy_toolbar = activity_toolbar
+else:
+pippy_toolbar = self.get_toolbar_box().toolbar
+
 # The go button
 goicon_bw = gtk.Image()
 goicon_bw.set_from_file(%s/icons/run_bw.svg % os.getcwd())
@@ -92,7 +130,7 @@ class PippyActivity(ViewSourceActivity, 
groupthink.sugar_tools.GroupActivity):
 gobutton.connect('clicked', self.flash_cb, dict({'bw':goicon_bw,
 'color':goicon_color}))
 gobutton.connect('clicked', 

[Sugar-devel] [PATCH] fix SL #2001 - Write does not pass parent window xid to ObjectChooser

2010-10-14 Thread godiard
From: Gonzalo Odiard godi...@sugarlabs.org

This is a regresion, probably introduced when changed the toolbar.
May be pass self.abiword_canvas and self to ImageToolbar is not the smarter 
option.
---
 AbiWordActivity.py |2 +-
 toolbar.py |5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/AbiWordActivity.py b/AbiWordActivity.py
index f6c54fa..7deab8c 100644
--- a/AbiWordActivity.py
+++ b/AbiWordActivity.py
@@ -110,7 +110,7 @@ class AbiWordActivity (activity.Activity):
 toolbar_box.toolbar.insert(list_toolbar, -1)
 
 insert_toolbar = ToolbarButton()
-insert_toolbar.props.page = InsertToolbar(self.abiword_canvas)
+insert_toolbar.props.page = InsertToolbar(self.abiword_canvas, self)
 insert_toolbar.props.icon_name = 'insert-table'
 insert_toolbar.props.label = _('Table')
 toolbar_box.toolbar.insert(insert_toolbar, -1)
diff --git a/toolbar.py b/toolbar.py
index 75243c7..a16803c 100644
--- a/toolbar.py
+++ b/toolbar.py
@@ -176,10 +176,11 @@ class EditToolbar(gtk.Toolbar):
 tool_item.show()
 
 class InsertToolbar(gtk.Toolbar):
-def __init__(self, abiword_canvas):
+def __init__(self, abiword_canvas, parent):
 gtk.Toolbar.__init__(self)
 
 self._abiword_canvas = abiword_canvas
+self._parent = parent
 
 self._table = abiword.TableCreator()
 self._table.set_labels(_('Table'), _('Cancel'))
@@ -234,7 +235,7 @@ class InsertToolbar(gtk.Toolbar):
 def cb(object):
 logging.debug('ObjectChooser: %r' % object)
 self._abiword_canvas.insert_image(object.file_path, True)
-chooser.pick(what=chooser.IMAGE, cb=cb)
+chooser.pick(parent=self._parent, what=chooser.IMAGE, cb=cb)
 
 def _table_cb(self, abi, rows, cols):
 self._abiword_canvas.insert_table(rows, cols)
-- 
1.7.2.3

___
Sugar-devel mailing list
Sugar-devel@lists.sugarlabs.org
http://lists.sugarlabs.org/listinfo/sugar-devel


  1   2   >