Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSayamindu Dasgupta <sayamindu@gmail.com>2009-08-05 08:34:30 (GMT)
committer Sayamindu Dasgupta <sayamindu@gmail.com>2009-08-05 08:34:30 (GMT)
commit76283f7761813fb09502e526a89e6bdbda28e91b (patch)
tree2192928a41724641e477050fdb7ec80bfd4d845b
parentab7c9f6521554f886ec12247d7cdcc7bfb71e03e (diff)
Add support for notes associated with bookmark
-rw-r--r--readdialog.py182
-rw-r--r--readsidebar.py112
2 files changed, 277 insertions, 17 deletions
diff --git a/readdialog.py b/readdialog.py
new file mode 100644
index 0000000..24e7d33
--- /dev/null
+++ b/readdialog.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+
+# Stolen from the PyGTK demo module by Maik Hertha <maik.hertha@berlin.de>
+
+import gtk
+import gobject
+
+from sugar.graphics import style
+from sugar.graphics.toolbutton import ToolButton
+
+from gettext import gettext as _
+import cjson
+
+class BaseReadDialog(gtk.Window):
+ def __init__(self, parent_xid, dialog_title):
+ gtk.Window.__init__(self)
+
+ self.connect('realize', self.__realize_cb)
+
+ self.set_decorated(False)
+ self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
+ self.set_border_width(style.LINE_WIDTH)
+
+ width = gtk.gdk.screen_width() - style.GRID_CELL_SIZE * 4
+ height = gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 4
+ self.set_size_request(width, height)
+
+ self._parent_window_xid = parent_xid
+
+ _vbox = gtk.VBox(spacing=2)
+ self.add(_vbox)
+
+ self.toolbar = gtk.Toolbar()
+ label = gtk.Label()
+ label.set_markup('<b> %s</b>' % dialog_title)
+ label.set_alignment(0, 0.5)
+ tool_item = gtk.ToolItem()
+ tool_item.add(label)
+ label.show()
+ self.toolbar.insert(tool_item, -1)
+ tool_item.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_expand(True)
+ self.toolbar.insert(separator, -1)
+ separator.show()
+ stop = ToolButton(icon_name='dialog-cancel')
+ stop.set_tooltip(_('Cancel'))
+ stop.connect('clicked', lambda *w: self.destroy())
+ self.toolbar.insert(stop, -1)
+ stop.show()
+
+ accept = ToolButton(icon_name='dialog-ok')
+ accept.set_tooltip(_('Ok'))
+ accept.connect('clicked', self.accept_clicked_cb)
+ accept.show()
+ self.toolbar.insert(accept, -1)
+
+ _vbox.pack_start(self.toolbar, expand=False)
+ self.toolbar.show()
+
+ self._event_box = gtk.EventBox()
+ _vbox.pack_start(self._event_box, expand=True, fill = True)
+ self._canvas = None
+
+ def set_canvas(self, canvas):
+ if self._canvas is not None:
+ self._event_box.remove(self._canvas)
+ self._event_box.add(canvas)
+ self._canvas = canvas
+
+ def __realize_cb(self, widget):
+ self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
+ self.window.set_accept_focus(True)
+
+ parent = gtk.gdk.window_foreign_new(self._parent_window_xid)
+ self.window.set_transient_for(parent)
+
+ self.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_WHITE.get_gdk_color())
+
+ if self._canvas is not None:
+ self._canvas.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_WHITE.get_gdk_color())
+ self._canvas.grab_focus()
+
+ self._event_box.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_WHITE.get_gdk_color())
+
+ def accept_clicked_cb(self, widget):
+ raise NotImplementedError
+
+
+class BookmarkDialog(BaseReadDialog):
+ def __init__(self, parent_xid, dialog_title, bookmark_title, bookmark_content, page, sidebarinstance):
+ BaseReadDialog.__init__(self, parent_xid, dialog_title)
+
+ self._sidebarinstance = sidebarinstance
+ self._page = page
+
+ vbox = gtk.VBox()
+ thbox = gtk.HBox()
+ vbox.pack_start(thbox, expand = False, fill = False)
+ thbox.set_border_width(style.DEFAULT_SPACING * 2)
+ thbox.set_spacing(style.DEFAULT_SPACING)
+ thbox.show()
+
+ label_title = gtk.Label(_('<b>Title</b>:'))
+ label_title.set_use_markup(True)
+ label_title.set_alignment(1, 0.5)
+ label_title.modify_fg(gtk.STATE_NORMAL,
+ style.COLOR_SELECTION_GREY.get_gdk_color())
+ thbox.pack_start(label_title, expand=False, fill = False)
+ label_title.show()
+
+ self._title_entry = gtk.Entry()
+ self._title_entry.modify_bg(gtk.STATE_INSENSITIVE,
+ style.COLOR_WHITE.get_gdk_color())
+ self._title_entry.modify_base(gtk.STATE_INSENSITIVE,
+ style.COLOR_WHITE.get_gdk_color())
+ self._title_entry.set_size_request(int(gtk.gdk.screen_width() / 3), -1)
+
+ thbox.pack_start(self._title_entry, expand = False, fill = False)
+ self._title_entry.show()
+ if bookmark_title is not None:
+ self._title_entry.set_text(bookmark_title)
+
+
+ cvbox = gtk.VBox()
+ vbox.pack_start(cvbox, expand = True, fill = True)
+ cvbox.set_border_width(style.DEFAULT_SPACING * 2)
+ cvbox.set_spacing(style.DEFAULT_SPACING/2)
+ cvbox.show()
+
+ label_content = gtk.Label(_('<b>Details</b>:'))
+ label_content.set_use_markup(True)
+ label_content.set_alignment(0, 0)
+ label_content.modify_fg(gtk.STATE_NORMAL,
+ style.COLOR_SELECTION_GREY.get_gdk_color())
+ cvbox.pack_start(label_content, expand=False, fill = False)
+ label_content.show()
+
+ sw = gtk.ScrolledWindow()
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ self._content_entry = gtk.TextView()
+ self._content_entry.set_wrap_mode(gtk.WRAP_WORD)
+
+ sw.add(self._content_entry)
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+
+ cvbox.pack_start(sw, expand = True, fill = True)
+ self._content_entry.show()
+ if bookmark_content is not None:
+ buffer = self._content_entry.get_buffer()
+ buffer.set_text(bookmark_content)
+
+ self.set_canvas(vbox)
+
+class BookmarkAddDialog(BookmarkDialog):
+ def __init__(self, parent_xid, dialog_title, bookmark_title, bookmark_content, page, sidebarinstance):
+ BookmarkDialog.__init__(self, parent_xid, dialog_title, bookmark_title, bookmark_content, page, sidebarinstance)
+
+ def accept_clicked_cb(self, widget):
+ title = self._title_entry.get_text()
+ details = self._content_entry.get_buffer().props.text
+ content = {'title' : unicode(title), 'content' : unicode(details)}
+ self._sidebarinstance._real_add_bookmark(self._page, cjson.encode(content))
+ self.destroy()
+
+class BookmarkEditDialog(BookmarkDialog):
+ def __init__(self, parent_xid, dialog_title, bookmark_title, bookmark_content, page, sidebarinstance):
+ BookmarkDialog.__init__(self, parent_xid, dialog_title, bookmark_title, bookmark_content, page, sidebarinstance)
+
+ def accept_clicked_cb(self, widget):
+ title = self._title_entry.get_text()
+ details = self._content_entry.get_buffer().props.text
+ content = {'title' : unicode(title), 'content' : unicode(details)}
+ self._sidebarinstance.del_bookmark(self._page)
+ self._sidebarinstance._real_add_bookmark(self._page, cjson.encode(content))
+ self.destroy()
diff --git a/readsidebar.py b/readsidebar.py
index d5280cd..0b745c2 100644
--- a/readsidebar.py
+++ b/readsidebar.py
@@ -16,20 +16,25 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
-import time
+import time, cjson
import gtk
from sugar.graphics.icon import Icon
from sugar.graphics.xocolor import XoColor
+from sugar import profile
+from sugar.util import timestamp_to_elapsed_string
from readbookmark import Bookmark
from readdb import BookmarkManager
+from readdialog import BookmarkAddDialog, BookmarkEditDialog
from gettext import gettext as _
_logger = logging.getLogger('read-activity')
+#TODO: Add support for multiple bookmarks in a single page (required when sharing)
+
class Sidebar(gtk.EventBox):
def __init__(self):
gtk.EventBox.__init__(self)
@@ -45,35 +50,98 @@ class Sidebar(gtk.EventBox):
self._box.show()
self.show()
- self._bookmarks = []
+ self._bookmark_icon = None
self._bookmark_manager = None
self._is_showing_local_bookmark = False
+ self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+
def _add_bookmark_icon(self, bookmark):
xocolor = XoColor(bookmark.color)
- bookmark_icon = Icon(icon_name = 'emblem-favorite', \
+ self._bookmark_icon = Icon(icon_name = 'emblem-favorite', \
pixel_size = 18, xo_color = xocolor)
- tooltip_text = (_('Bookmark added by %(user)s on %(time)s') \
- % {'user': bookmark.nick, 'time': time.ctime(bookmark.timestamp)})
- bookmark_icon.set_tooltip_text(tooltip_text)
+ self._bookmark_icon.props.has_tooltip = True
+ self.__bookmark_icon_query_tooltip_cb_id = \
+ self._bookmark_icon.connect('query_tooltip', self.__bookmark_icon_query_tooltip_cb, \
+ bookmark)
- self._box.pack_start(bookmark_icon ,expand=False,fill=False)
- bookmark_icon.show_all()
-
- self._bookmarks.append(bookmark_icon)
+ self.__event_cb_id = \
+ self.connect('event', self.__event_cb, bookmark)
+
+ self._box.pack_start(self._bookmark_icon ,expand=False,fill=False)
+ self._bookmark_icon.show_all()
if bookmark.is_local():
self._is_showing_local_bookmark = True
- def _clear_bookmarks(self):
- for bookmark_icon in self._bookmarks:
- bookmark_icon.hide() #XXX: Is this needed??
- bookmark_icon.destroy()
+ def __bookmark_icon_query_tooltip_cb(self, widget, x, y, keyboard_mode, tip, bookmark):
+ content = cjson.decode(bookmark.title)
- self._bookmarks = []
+ tooltip_header = content['title']
+ tooltip_body = content['content']
+ #TRANS: This goes like Bookmark added by User 5 days ago (the elapsed string gets translated
+ #TRANS: automatically)
+ tooltip_footer = (_('Bookmark added by %(user)s %(time)s') \
+ % {'user': bookmark.nick, 'time': timestamp_to_elapsed_string(bookmark.timestamp)})
+
+ vbox = gtk.VBox()
+
+ l = gtk.Label('<big>%s</big>' % tooltip_header)
+ l.set_use_markup(True)
+ l.set_width_chars(40)
+ l.set_line_wrap(True)
+ vbox.pack_start(l, expand = False, fill = False)
+ l.show()
+
+ l = gtk.Label('%s' % tooltip_body)
+ l.set_use_markup(True)
+ l.set_alignment(0, 0)
+ l.set_padding(2, 6)
+ l.set_width_chars(40)
+ l.set_line_wrap(True)
+ l.set_justify(gtk.JUSTIFY_FILL)
+ vbox.pack_start(l, expand = True, fill = True)
+ l.show()
+
+ l = gtk.Label('<small><i>%s</i></small>' % tooltip_footer)
+ l.set_use_markup(True)
+ l.set_width_chars(40)
+ l.set_line_wrap(True)
+ vbox.pack_start(l, expand = False, fill = False)
+ l.show()
+
+ tip.set_custom(vbox)
+
+ return True
- self._is_showing_local_bookmark = False
+ def __event_cb(self, widget, event, bookmark):
+ if event.type == gtk.gdk.BUTTON_PRESS and \
+ self._bookmark_icon is not None:
+ content = cjson.decode(bookmark.title)
+ bookmark_title = content['title']
+ bookmark_content = content['content']
+
+ dialog = BookmarkEditDialog(parent_xid = self.get_toplevel().window.xid, \
+ dialog_title = _("Add notes for bookmark: "), \
+ bookmark_title = bookmark_title, \
+ bookmark_content = bookmark_content, page = bookmark.page_no, \
+ sidebarinstance = self)
+ dialog.show_all()
+
+ return False
+
+ def _clear_bookmarks(self):
+ if self._bookmark_icon is not None:
+ self._bookmark_icon.disconnect(self.__bookmark_icon_query_tooltip_cb_id)
+ self.disconnect(self.__event_cb_id)
+
+ self._bookmark_icon.hide() #XXX: Is this needed??
+ self._bookmark_icon.destroy()
+
+ self._bookmark_icon = None
+
+ self._is_showing_local_bookmark = False
def set_bookmarkmanager(self, filehash):
self._bookmark_manager = BookmarkManager(filehash)
@@ -92,7 +160,17 @@ class Sidebar(gtk.EventBox):
self._add_bookmark_icon(bookmark)
def add_bookmark(self, page):
- self._bookmark_manager.add_bookmark(page, '') #TODO: Implement title support
+ bookmark_title = (_("%s's bookmark") % profile.get_nick_name())
+ bookmark_content = (_("Bookmark for page %d") % page)
+ dialog = BookmarkAddDialog(parent_xid = self.get_toplevel().window.xid, \
+ dialog_title = _("Add notes for bookmark: "), \
+ bookmark_title = bookmark_title, \
+ bookmark_content = bookmark_content, page = page, \
+ sidebarinstance = self)
+ dialog.show_all()
+
+ def _real_add_bookmark(self, page, content):
+ self._bookmark_manager.add_bookmark(page, unicode(content))
self.update_for_page(page)
def del_bookmark(self, page):