[Sugar-devel] [PATCH] Sort the activities in the home in alphabetic order
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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.
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
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
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
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
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
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
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
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
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
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
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
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