Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/sugar/activity/Makefile.am3
-rw-r--r--src/sugar/activity/activity.py62
-rw-r--r--src/sugar/activity/namingalert.py312
-rw-r--r--src/sugar/graphics/Makefile.am1
-rw-r--r--src/sugar/graphics/canvastextview.py39
5 files changed, 359 insertions, 58 deletions
diff --git a/src/sugar/activity/Makefile.am b/src/sugar/activity/Makefile.am
index ca1fa61..91f6ea8 100644
--- a/src/sugar/activity/Makefile.am
+++ b/src/sugar/activity/Makefile.am
@@ -6,4 +6,5 @@ sugar_PYTHON = \
activityhandle.py \
activityservice.py \
bundlebuilder.py \
- main.py
+ main.py \
+ namingalert.py \ No newline at end of file
diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py
index f3ee5b8..d2ba278 100644
--- a/src/sugar/activity/activity.py
+++ b/src/sugar/activity/activity.py
@@ -30,7 +30,7 @@ will need for a real activity.
STABLE.
"""
# Copyright (C) 2006-2007 Red Hat, Inc.
-# Copyright (C) 2007-2008 One Laptop Per Child
+# Copyright (C) 2007-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
@@ -55,7 +55,8 @@ from hashlib import sha1
import traceback
import gconf
-import gtk, gobject
+import gtk
+import gobject
import dbus
import dbus.service
import cjson
@@ -63,6 +64,7 @@ import cjson
from sugar import util
from sugar.presence import presenceservice
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.toolbox import Toolbox
@@ -74,7 +76,6 @@ from sugar.graphics.xocolor import XoColor
from sugar.datastore import datastore
from sugar.session import XSMPClient
from sugar import wm
-from sugar import _sugarext
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
@@ -353,59 +354,6 @@ class _ActivitySession(gobject.GObject):
def __sm_quit_cb(self, client):
self.emit('quit')
-class TitleAlert(gtk.Window):
- __gtype_name__ = 'SugarTitleAlert'
-
- _BACKGROUND_COLOR = style.COLOR_BLACK.get_gdk_color()
-
- def __init__(self, activity):
- gtk.Window.__init__(self)
-
- self.set_border_width(style.LINE_WIDTH)
- offset = style.GRID_CELL_SIZE
- width = gtk.gdk.screen_width() - offset * 2
- height = gtk.gdk.screen_height() - offset * 2
- self.set_size_request(width, height)
- self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
- self.set_decorated(False)
- self.set_resizable(False)
- self.set_modal(True)
- self.connect('realize', self.__realize_cb)
-
- self._activity = activity
-
- alignment = gtk.Alignment(xalign=0.5, yalign=0.5)
- self.add(alignment)
- alignment.show()
-
- vbox = gtk.VBox()
- vbox.set_spacing(style.DEFAULT_PADDING)
- alignment.add(vbox)
- vbox.show()
-
- self._entry = gtk.Entry()
- self._entry.props.text=self._activity.metadata['title']
- self._entry.modify_bg(gtk.STATE_INSENSITIVE, self._BACKGROUND_COLOR)
- self._entry.modify_base(gtk.STATE_INSENSITIVE, self._BACKGROUND_COLOR)
- vbox.pack_start(self._entry)
- self._entry.show()
- self._entry.connect('activate', self.__activate_cb)
-
- button = gtk.Button(_('Keep'))
- vbox.pack_start(button)
- button.show()
- button.connect('clicked', self.__activate_cb)
-
- def __realize_cb(self, widget):
- self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
- self.window.set_accept_focus(True)
- self.modify_bg(gtk.STATE_NORMAL, self._BACKGROUND_COLOR)
-
- def __activate_cb(self, widget):
- self._activity.metadata['title'] = self._entry.props.text
- self._activity.metadata['title_set_by_user'] = '1'
- self._activity.close()
-
class Activity(Window, gtk.Container):
"""This is the base Activity class that all other Activities derive from.
This is where your activity starts.
@@ -1027,7 +975,7 @@ class Activity(Window, gtk.Container):
if not self._updating_jobject:
self._complete_close()
else:
- title_alert = TitleAlert(self)
+ title_alert = NamingAlert(self, get_bundle_path())
title_alert.set_transient_for(self.get_toplevel())
title_alert.show()
diff --git a/src/sugar/activity/namingalert.py b/src/sugar/activity/namingalert.py
new file mode 100644
index 0000000..8470542
--- /dev/null
+++ b/src/sugar/activity/namingalert.py
@@ -0,0 +1,312 @@
+# 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 gtk
+import gobject
+import hippo
+import gconf
+
+from sugar.graphics import style
+from sugar.graphics.icon import Icon
+from sugar.graphics.xocolor import XoColor
+from sugar.graphics.icon import CanvasIcon
+from sugar.graphics.entry import CanvasEntry
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.canvastextview import CanvasTextView
+
+from sugar.bundle.activitybundle import ActivityBundle
+
+_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
+
+class NamingToolbar(gtk.Toolbar):
+ """ Toolbar of the naming alert
+ """
+ __gtype_name__ = 'SugarNamingToolbar'
+
+ __gsignals__ = {
+ 'keep-clicked': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ ([]))
+ }
+ def __init__(self):
+ gtk.Toolbar.__init__(self)
+
+ client = gconf.client_get_default()
+ color = XoColor(client.get_string('/desktop/sugar/user/color'))
+ icon = Icon()
+ icon.set_from_icon_name('activity-journal',
+ gtk.ICON_SIZE_LARGE_TOOLBAR)
+ icon.props.xo_color = color
+ self._add_widget(icon)
+
+ self._add_separator()
+
+ self._title = gtk.Label(_('Name this entry'))
+ self._add_widget(self._title)
+
+ self._add_separator(True)
+
+ self._keep_button = ToolButton('dialog-ok')
+ self._keep_button.set_tooltip(_('Keep'))
+ self._keep_button.connect('clicked', self.__keep_button_clicked_cb)
+ self.insert(self._keep_button, -1)
+ self._keep_button.show()
+
+ def _add_separator(self, expand=False):
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ if expand:
+ separator.set_expand(True)
+ else:
+ separator.set_size_request(style.DEFAULT_SPACING, -1)
+ self.insert(separator, -1)
+ separator.show()
+
+ def _add_widget(self, widget, expand=False):
+ tool_item = gtk.ToolItem()
+ tool_item.set_expand(expand)
+
+ tool_item.add(widget)
+ widget.show()
+
+ self.insert(tool_item, -1)
+ tool_item.show()
+
+ def __keep_button_clicked_cb(self, widget, data=None):
+ self.emit('keep-clicked')
+
+class FavoriteIcon(CanvasIcon):
+ def __init__(self, favorite):
+ CanvasIcon.__init__(self, icon_name='emblem-favorite',
+ box_width=style.GRID_CELL_SIZE * 3 / 5,
+ size=style.SMALL_ICON_SIZE)
+ self._favorite = None
+ self.set_favorite(favorite)
+ self.connect('button-release-event', self.__release_event_cb)
+ self.connect('motion-notify-event', self.__motion_notify_event_cb)
+
+ def set_favorite(self, favorite):
+ if favorite == self._favorite:
+ return
+
+ self._favorite = favorite
+ if favorite:
+ client = gconf.client_get_default()
+ color = XoColor(client.get_string('/desktop/sugar/user/color'))
+ self.props.xo_color = color
+ else:
+ self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
+ self.props.fill_color = style.COLOR_WHITE.get_svg()
+
+ def get_favorite(self):
+ return self._favorite
+
+ favorite = gobject.property(
+ type=bool, default=False, getter=get_favorite, setter=set_favorite)
+
+ def __release_event_cb(self, icon, event):
+ self.props.favorite = not self.props.favorite
+
+ def __motion_notify_event_cb(self, icon, event):
+ if not self._favorite:
+ if event.detail == hippo.MOTION_DETAIL_ENTER:
+ icon.props.fill_color = style.COLOR_BUTTON_GREY.get_svg()
+ elif event.detail == hippo.MOTION_DETAIL_LEAVE:
+ icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
+
+class NamingAlert(gtk.Window):
+ __gtype_name__ = 'SugarNamingAlert'
+
+ def __init__(self, activity, bundle_path):
+ gtk.Window.__init__(self)
+
+ self._bundle_path = bundle_path
+ self._favorite_icon = None
+ self._title = None
+ self._description = None
+ self._tags = None
+
+ self.set_border_width(style.LINE_WIDTH)
+ offset = style.GRID_CELL_SIZE
+ width = gtk.gdk.screen_width() - offset * 2
+ height = gtk.gdk.screen_height() - offset * 2
+ self.set_size_request(width, height)
+ self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
+ self.set_decorated(False)
+ self.set_resizable(False)
+ self.set_modal(True)
+ self.connect('realize', self.__realize_cb)
+
+ self._activity = activity
+
+ vbox = gtk.VBox()
+ self.add(vbox)
+ vbox.show()
+
+ toolbar = NamingToolbar()
+ toolbar.connect('keep-clicked', self.__keep_cb)
+ vbox.pack_start(toolbar, False)
+ toolbar.show()
+
+ canvas = hippo.Canvas()
+ self._root = hippo.CanvasBox()
+ self._root.props.background_color = style.COLOR_WHITE.get_int()
+ canvas.set_root(self._root)
+ vbox.pack_start(canvas)
+ canvas.show()
+
+ body = self._create_body()
+ self._root.append(body, hippo.PACK_EXPAND)
+
+ def _create_body(self):
+ body = hippo.CanvasBox()
+ body.props.orientation = hippo.ORIENTATION_VERTICAL
+ body.props.background_color = style.COLOR_WHITE.get_int()
+ body.props.padding_top = style.DEFAULT_SPACING * 3
+
+ header = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
+ padding=style.DEFAULT_PADDING,
+ padding_right=style.GRID_CELL_SIZE,
+ spacing=style.DEFAULT_SPACING)
+ body.append(header)
+
+ descriptions = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
+ spacing=style.DEFAULT_SPACING * 3,
+ padding_left=style.GRID_CELL_SIZE,
+ padding_right=style.GRID_CELL_SIZE,
+ padding_top=style.DEFAULT_SPACING * 3)
+
+ body.append(descriptions, hippo.PACK_EXPAND)
+
+ first_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
+ spacing=style.DEFAULT_SPACING)
+ descriptions.append(first_column)
+
+ second_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
+ spacing=style.DEFAULT_SPACING)
+ descriptions.append(second_column, hippo.PACK_EXPAND)
+
+ self._favorite_icon = self._create_favorite_icon()
+ header.append(self._favorite_icon)
+
+ activity_icon = self._create_activity_icon()
+ header.append(activity_icon)
+
+ self._title = self._create_title()
+ header.append(self._title, hippo.PACK_EXPAND)
+
+ if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
+ header.reverse()
+
+ description_box, self._description = self._create_description()
+ second_column.append(description_box)
+
+ tags_box, self._tags = self._create_tags()
+ second_column.append(tags_box)
+
+ return body
+
+ def _create_favorite_icon(self):
+ favorite_icon = FavoriteIcon(False)
+ return favorite_icon
+
+ def _create_activity_icon(self):
+ activity_bundle = ActivityBundle(self._bundle_path)
+ activity_icon = CanvasIcon(file_name=activity_bundle.get_icon())
+ if self._activity.metadata.has_key('icon-color') and \
+ self._activity.metadata['icon-color']:
+ activity_icon.props.xo_color = XoColor( \
+ self._activity.metadata['icon-color'])
+ return activity_icon
+
+ def _create_title(self):
+ title = CanvasEntry()
+ title.set_background(style.COLOR_WHITE.get_html())
+ title.props.text = self._activity.metadata.get('title', _('Untitled'))
+ return title
+
+ def _create_description(self):
+ vbox = hippo.CanvasBox()
+ vbox.props.spacing = style.DEFAULT_SPACING
+
+ text = hippo.CanvasText(text=_('Description:'),
+ font_desc=style.FONT_NORMAL.get_pango_desc())
+ text.props.color = style.COLOR_BUTTON_GREY.get_int()
+
+ if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
+ text.props.xalign = hippo.ALIGNMENT_END
+ else:
+ text.props.xalign = hippo.ALIGNMENT_START
+
+ vbox.append(text)
+
+ description = self._activity.metadata.get('description', '')
+ text_view = CanvasTextView(description,
+ box_height=style.GRID_CELL_SIZE * 2)
+ vbox.append(text_view, hippo.PACK_EXPAND)
+
+ text_view.text_view_widget.props.accepts_tab = False
+
+ return vbox, text_view
+
+ def _create_tags(self):
+ vbox = hippo.CanvasBox()
+ vbox.props.spacing = style.DEFAULT_SPACING
+
+ text = hippo.CanvasText(text=_('Tags:'),
+ font_desc=style.FONT_NORMAL.get_pango_desc())
+ text.props.color = style.COLOR_BUTTON_GREY.get_int()
+
+ if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
+ text.props.xalign = hippo.ALIGNMENT_END
+ else:
+ text.props.xalign = hippo.ALIGNMENT_START
+
+ vbox.append(text)
+
+ tags = self._activity.metadata.get('tags', '')
+ text_view = CanvasTextView(tags, box_height=style.GRID_CELL_SIZE * 2)
+ vbox.append(text_view, hippo.PACK_EXPAND)
+
+ text_view.text_view_widget.props.accepts_tab = False
+
+ return vbox, text_view
+
+ def __realize_cb(self, widget):
+ self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
+ self.window.set_accept_focus(True)
+
+ def __keep_cb(self, widget):
+ is_favorite = self._favorite_icon.get_favorite()
+ if is_favorite:
+ self._activity.metadata['keep'] = 1
+ else:
+ self._activity.metadata['keep'] = 0
+
+ self._activity.metadata['title'] = self._title.props.text
+
+ new_tags = self._tags.text_view_widget.props.buffer.props.text
+ self._activity.metadata['tags'] = new_tags
+
+ new_description = \
+ self._description.text_view_widget.props.buffer.props.text
+ self._activity.metadata['description'] = new_description
+
+ self._activity.metadata['title_set_by_user'] = '1'
+ self._activity.close()
diff --git a/src/sugar/graphics/Makefile.am b/src/sugar/graphics/Makefile.am
index 3f147b4..c4d5e61 100644
--- a/src/sugar/graphics/Makefile.am
+++ b/src/sugar/graphics/Makefile.am
@@ -3,6 +3,7 @@ sugar_PYTHON = \
__init__.py \
alert.py \
animator.py \
+ canvastextview.py \
combobox.py \
colorbutton.py \
entry.py \
diff --git a/src/sugar/graphics/canvastextview.py b/src/sugar/graphics/canvastextview.py
new file mode 100644
index 0000000..481248d
--- /dev/null
+++ b/src/sugar/graphics/canvastextview.py
@@ -0,0 +1,39 @@
+# Copyright (C) 2008 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 gtk
+import hippo
+
+from sugar.graphics import style
+
+class CanvasTextView(hippo.CanvasWidget):
+ def __init__(self, text, **kwargs):
+ hippo.CanvasWidget.__init__(self, **kwargs)
+ self.text_view_widget = gtk.TextView()
+ self.text_view_widget.props.buffer.props.text = text
+ self.text_view_widget.props.left_margin = style.DEFAULT_SPACING
+ self.text_view_widget.props.right_margin = style.DEFAULT_SPACING
+ self.text_view_widget.props.wrap_mode = gtk.WRAP_WORD
+ self.text_view_widget.show()
+
+ # TODO: These fields should expand vertically instead of scrolling
+ scrolled_window = gtk.ScrolledWindow()
+ scrolled_window.set_shadow_type(gtk.SHADOW_OUT)
+ scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ scrolled_window.add(self.text_view_widget)
+
+ self.props.widget = scrolled_window