Codebase list sugar-read-activity / ac6ac17
Bookmark support Sayamindu Dasgupta 15 years ago
6 changed file(s) with 233 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
Binary diff not shown
3333 from sugar.graphics.objectchooser import ObjectChooser
3434
3535 from readtoolbar import EditToolbar, ReadToolbar, ViewToolbar
36 from readsidebar import Sidebar
3637
3738 _HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager'
3839 _HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager'
108109 self._view.set_screen_dpi(_get_screen_dpi())
109110 self._view.connect('notify::has-selection',
110111 self._view_notify_has_selection_cb)
112
113 self._sidebar = Sidebar()
114 self._sidebar.show()
111115
112116 toolbox = activity.ActivityToolbox(self)
113117
121125 toolbox.add_toolbar(_('Edit'), self._edit_toolbar)
122126 self._edit_toolbar.show()
123127
124 self._read_toolbar = ReadToolbar(self._view)
128 self._read_toolbar = ReadToolbar(self._view, self._sidebar)
125129 toolbox.add_toolbar(_('Read'), self._read_toolbar)
126130 self._read_toolbar.show()
127131
136140 self.set_toolbox(toolbox)
137141 toolbox.show()
138142
139 scrolled = gtk.ScrolledWindow()
140 scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
141 scrolled.props.shadow_type = gtk.SHADOW_NONE
142
143 scrolled.add(self._view)
143 self._scrolled = gtk.ScrolledWindow()
144 self._scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
145 self._scrolled.props.shadow_type = gtk.SHADOW_NONE
146
147 self._scrolled.add(self._view)
144148 self._view.show()
145
146 self.set_canvas(scrolled)
147 scrolled.show()
149
150 hbox = gtk.HBox()
151 hbox.pack_start(self._sidebar, expand=False, fill=False)
152 hbox.pack_start(self._scrolled, expand=True, fill=True)
153
154 self.set_canvas(hbox)
155 self._scrolled.show()
156 hbox.show()
148157
149158 # Set up for idle suspend
150159 self._idle_timer = 0
169178 _HARDWARE_MANAGER_OBJECT_PATH)
170179 self._service = dbus.Interface(proxy,
171180 _HARDWARE_MANAGER_INTERFACE)
172 scrolled.props.vadjustment.connect("value-changed",
181 self._scrolled.props.vadjustment.connect("value-changed",
173182 self._user_action_cb)
174 scrolled.props.hadjustment.connect("value-changed",
183 self._scrolled.props.hadjustment.connect("value-changed",
175184 self._user_action_cb)
176185 self.connect("focus-in-event", self._focus_in_event_cb)
177186 self.connect("focus-out-event", self._focus_out_event_cb)
446455 self._want_document = False
447456 self._view.set_document(self._document)
448457 self._edit_toolbar.set_document(self._document)
449 self._read_toolbar.set_document(self._document)
458 self._read_toolbar.set_document(self._document, filepath)
450459
451460 if not self.metadata['title_set_by_user'] == '1':
452461 info = self._document.get_info()
460469 _logger.debug('Found sizing mode: %s', sizing_mode)
461470 if sizing_mode == "best-fit":
462471 self._view.props.sizing_mode = evince.SIZING_BEST_FIT
463 self._view.update_view_size(self.canvas)
472 self._view.update_view_size(self._scrolled)
464473 elif sizing_mode == "free":
465474 self._view.props.sizing_mode = evince.SIZING_FREE
466475 self._view.props.zoom = float(self.metadata.get('Read_zoom', '1.0'))
467476 _logger.debug('Set zoom to %f', self._view.props.zoom)
468477 elif sizing_mode == "fit-width":
469478 self._view.props.sizing_mode = evince.SIZING_FIT_WIDTH
470 self._view.update_view_size(self.canvas)
479 self._view.update_view_size(self._scrolled)
471480 else:
472481 # this may happen when we get a document from a buddy with a later
473482 # version of Read, for example.
577586 _logger.debug("Keyname Release: %s, time: %s", keyname, event.time)
578587
579588 def __view_toolbar_needs_update_size_cb(self, view_toolbar):
580 self._view.update_view_size(self.canvas)
589 self._view.update_view_size(self._scrolled)
581590
582591 def __view_toolbar_go_fullscreen_cb(self, view_toolbar):
583592 self.fullscreen()
0 class Bookmark:
1 def __init__(self, data):
2 self.md5 = data[0]
3 self.page_no = data[1]
4 self.title = data[2]
5 self.timestamp = data[3]
6 self.nick = data[4]
7 self.color = data[5]
8 self.local = data[6]
9
10 def belongstopage(self, page_no):
11 return self.page_no == page_no
12
13 def is_local(self):
14 return bool(self.local)
0 import logging
1
2 import sqlite3
3 import time
4
5 import gconf
6
7 from readbookmark import Bookmark
8
9 _logger = logging.getLogger('read-activity')
10
11 class BookmarkManager:
12 def __init__(self, hash, dbpath='read.db'):
13 self._hash = hash
14 self._conn = sqlite3.connect(dbpath)
15 self._cur = self._conn.cursor()
16
17 self._bookmarks = []
18 self._populate_bookmarks()
19
20 def add_bookmark(self, page, title, local=1):
21 # locale = 0 means that this is a bookmark originally
22 # created by the person who originally shared the file
23 timestamp = time.time()
24 client = gconf.client_get_default()
25 user = client.get_string("/desktop/sugar/user/nick")
26 color = client.get_string("/desktop/sugar/user/color")
27
28 t = (self._hash, page, title, timestamp, user, color, local)
29 self._cur.execute('insert into bookmarks values (?, ?, ?, ?, ?, ?, ?)', t)
30 self._conn.commit()
31
32 self._resync_bookmark_cache()
33
34 def del_bookmark(self, page):
35 client = gconf.client_get_default()
36 user = client.get_string("/desktop/sugar/user/nick")
37
38 # We delete only the locally made bookmark
39
40 t = (self._hash, page, user)
41 self._cur.execute('delete from bookmarks where md5=? and page=? and user=?', t)
42 self._conn.commit()
43
44 self._resync_bookmark_cache()
45
46 def _populate_bookmarks(self):
47 # TODO: Figure out if caching the entire set of bookmarks is a good idea or not
48 self._cur.execute('select * from bookmarks where md5=?', (self._hash,))
49
50 for row in self._cur:
51 self._bookmarks.append(Bookmark(row))
52
53 def get_bookmarks_for_page(self, page):
54 bookmarks = []
55 for bookmark in self._bookmarks:
56 if bookmark.belongstopage(page):
57 bookmarks.append(bookmark)
58
59 return bookmarks
60
61 def _resync_bookmark_cache(self):
62 # To be called when a new bookmark has been added/removed
63 self._bookmarks = []
64 self._populate_bookmarks()
0 import logging
1
2 import gtk
3
4 from sugar.graphics.icon import Icon
5 from sugar.graphics.xocolor import XoColor
6
7 from readbookmark import Bookmark
8 from readdb import BookmarkManager
9
10 from gettext import gettext as _
11
12 _logger = logging.getLogger('read-activity')
13
14 class Sidebar(gtk.EventBox):
15 def __init__(self):
16 gtk.EventBox.__init__(self)
17 self.set_size_request(20, -1)
18 # Take care of the background first
19 white = gtk.gdk.color_parse("white")
20 self.modify_bg(gtk.STATE_NORMAL, white)
21
22 self._box = gtk.VButtonBox()
23 self._box.set_layout(gtk.BUTTONBOX_CENTER)
24 self.add(self._box)
25
26 self._box.show()
27 self.show()
28
29 self._bookmarks = []
30 self._bookmark_manager = None
31 self._is_showing_local_bookmark = False
32
33 def _add_bookmark_icon(self, bookmark):
34 xocolor = XoColor(bookmark.color)
35 bookmark_icon = Icon(icon_name = 'emblem-favorite', \
36 pixel_size = 18, xo_color = xocolor)
37 bookmark_icon.set_tooltip_text(_("Stupid tooltip"))
38 self._box.pack_start(bookmark_icon ,expand=False,fill=False)
39 bookmark_icon.show_all()
40
41 self._bookmarks.append(bookmark_icon)
42
43 if bookmark.is_local():
44 self._is_showing_local_bookmark = True
45
46 def _clear_bookmarks(self):
47 for bookmark_icon in self._bookmarks:
48 bookmark_icon.hide() #XXX: Is this needed??
49 bookmark_icon.destroy()
50
51 self._bookmarks = []
52
53 self._is_showing_local_bookmark = False
54
55 def set_bookmarkmanager(self, filehash):
56 self._bookmark_manager = BookmarkManager(filehash)
57
58 def update_for_page(self, page):
59 self._clear_bookmarks()
60 if self._bookmark_manager is None:
61 return
62
63 bookmarks = self._bookmark_manager.get_bookmarks_for_page(page)
64
65 for bookmark in bookmarks:
66 self._add_bookmark_icon(bookmark)
67
68 def add_bookmark(self, page):
69 self._bookmark_manager.add_bookmark(page, '') #TODO: Implement title support
70 self.update_for_page(page)
71
72 def del_bookmark(self, page):
73 self._bookmark_manager.del_bookmark(page)
74 self.update_for_page(page)
75
76 def is_showing_local_bookmark(self):
77 return self._is_showing_local_bookmark
2222 import gtk
2323 import evince
2424
25 import md5
26
2527 from sugar.graphics.toolbutton import ToolButton
28 from sugar.graphics.toggletoolbutton import ToggleToolButton
2629 from sugar.graphics.menuitem import MenuItem
2730 from sugar.graphics import iconentry
2831 from sugar.activity import activity
32 from sugar.graphics.icon import Icon
33 from sugar.graphics.xocolor import XoColor
34
35 def get_md5(filename): #FIXME: Should be moved somewhere else
36 filename = filename.replace('file://', '') #XXX: hack
37 fh = open(filename)
38 digest = md5.new()
39 while 1:
40 buf = fh.read(4096)
41 if buf == "":
42 break
43 digest.update(buf)
44 fh.close()
45 return digest.hexdigest()
46
2947
3048 class EditToolbar(activity.EditToolbar):
3149 __gtype_name__ = 'EditToolbar'
163181 class ReadToolbar(gtk.Toolbar):
164182 __gtype_name__ = 'ReadToolbar'
165183
166 def __init__(self, evince_view):
184 def __init__(self, evince_view, sidebar):
167185 gtk.Toolbar.__init__(self)
168186
169187 self._evince_view = evince_view
188 self._sidebar = sidebar
170189 self._document = None
171190
172191 self._back = ToolButton('go-previous')
235254 self.insert(navitem, -1)
236255 navitem.show()
237256
238
239 def set_document(self, document):
257 spacer = gtk.SeparatorToolItem()
258 self.insert(spacer, -1)
259 spacer.show()
260
261 bookmarkitem = gtk.ToolItem()
262 self._bookmarker = ToggleToolButton('emblem-favorite')
263 self._bookmarker_toggle_handler_id = self._bookmarker.connect('toggled',
264 self._bookmarker_toggled_cb)
265
266 bookmarkitem.add(self._bookmarker)
267
268 self.insert(bookmarkitem, -1)
269 bookmarkitem.show_all()
270
271 def set_document(self, document, filepath):
272 hash = get_md5(filepath)
240273 self._document = document
241274 page_cache = self._document.get_page_cache()
242275 page_cache.connect('page-changed', self._page_changed_cb)
243276 self._update_nav_buttons()
244277 self._update_toc()
278 self._sidebar.set_bookmarkmanager(hash)
245279
246280 def _num_page_entry_insert_text_cb(self, entry, text, length, position):
247281 if not re.match('[0-9]', text):
268302
269303 def _go_forward_cb(self, button):
270304 self._evince_view.next_page()
305
306 def _bookmarker_toggled_cb(self, button):
307 page = self._document.get_page_cache().get_current_page()
308 if self._bookmarker.props.active:
309 self._sidebar.add_bookmark(page)
310 else:
311 self._sidebar.del_bookmark(page)
271312
272313 def _page_changed_cb(self, page, proxy):
273314 self._update_nav_buttons()
274315 if hasattr(self._document, 'has_document_links'):
275316 if self._document.has_document_links():
276317 self._toc_select_active_page()
277
318
319 self._sidebar.update_for_page(self._document.get_page_cache().get_current_page())
320
321 self._bookmarker.handler_block(self._bookmarker_toggle_handler_id)
322 self._bookmarker.props.active = self._sidebar.is_showing_local_bookmark()
323 self._bookmarker.handler_unblock(self._bookmarker_toggle_handler_id)
324
278325 def _update_nav_buttons(self):
279326 current_page = self._document.get_page_cache().get_current_page()
280327 self._back.props.sensitive = current_page > 0