Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@sugarlabs.org>2011-02-18 17:27:29 (GMT)
committer Gonzalo Odiard <godiard@sugarlabs.org>2011-02-18 17:33:12 (GMT)
commitaa5534a95735df60c9cf619b6d463d2ec21abd95 (patch)
treecfcb4008b9333a7336eb97772ff48343d9050ef6
parent76cacfad48af182b1edefbdaf202b7edb4f43c81 (diff)
Add highlight support to thetext backend
- The highlights are saved in the same db we save the bookmarks. - The highlights can be removed selecting again the same tex, or a subportion of the text or puting the cursos inside the highlighted area.
-rw-r--r--epubadapter.py3
-rw-r--r--evinceadapter.py3
-rw-r--r--readactivity.py92
-rw-r--r--readdb.py81
-rw-r--r--readsidebar.py4
-rw-r--r--textadapter.py31
6 files changed, 184 insertions, 30 deletions
diff --git a/epubadapter.py b/epubadapter.py
index 964f915..b03966f 100644
--- a/epubadapter.py
+++ b/epubadapter.py
@@ -46,6 +46,9 @@ class EpubViewer(epubview.EpubView):
def can_zoom_to_width(self):
return False
+ def can_highlight(self):
+ return False
+
def connect_zoom_handler(self, handler):
self._zoom_handler = handler
self._view_notify_zoom_handler = \
diff --git a/evinceadapter.py b/evinceadapter.py
index ad79189..c37562c 100644
--- a/evinceadapter.py
+++ b/evinceadapter.py
@@ -109,6 +109,9 @@ class EvinceViewer():
self._model.props.sizing_mode)
self.metadata['Read_sizing_mode'] = "fit-width"
+ def can_highlight(self):
+ return False
+
def get_zoom(self):
'''
Returns the current zoom level
diff --git a/readactivity.py b/readactivity.py
index c063027..2a43084 100644
--- a/readactivity.py
+++ b/readactivity.py
@@ -48,7 +48,7 @@ from sugar.graphics.objectchooser import ObjectChooser
from readtoolbar import EditToolbar, ViewToolbar
from readsidebar import Sidebar
from readtopbar import TopBar
-
+from readdb import BookmarkManager
import epubadapter
import evinceadapter
import textadapter
@@ -234,6 +234,16 @@ class ReadActivity(activity.Activity):
toolbar_box.toolbar.insert(bookmark_item, -1)
bookmark_item.show()
+ self._highlight_item = gtk.ToolItem()
+ self._highlight = ToggleToolButton('format-text-underline')
+ self._highlight.set_tooltip(_('Highlight'))
+ self._highlight.props.sensitive = False
+ self._highlight_id = self._highlight.connect('clicked', \
+ self.__highlight_cb)
+ self._highlight_item.add(self._highlight)
+ toolbar_box.toolbar.insert(self._highlight_item, -1)
+ self._highlight_item.show_all()
+
separator = gtk.SeparatorToolItem()
separator.props.draw = False
separator.set_expand(True)
@@ -417,19 +427,45 @@ class ReadActivity(activity.Activity):
def __go_forward_page_cb(self, button):
self._view.next_page()
+ def __highlight_cb(self, button):
+ tuples_list = self._bookmarkmanager.get_highlights(
+ self._view.get_current_page())
+ selection_tuple = self._view.get_selection_bounds()
+ cursor_position = self._view.get_cursor_position()
+
+ old_highlight_found = None
+ for compare_tuple in tuples_list:
+ if selection_tuple:
+ if selection_tuple[0] >= compare_tuple[0] and \
+ selection_tuple[1] <= compare_tuple[1]:
+ old_highlight_found = compare_tuple
+ break
+ if cursor_position >= compare_tuple[0] and \
+ cursor_position <= compare_tuple[1]:
+ old_highlight_found = compare_tuple
+ break
+
+ if old_highlight_found == None:
+ self._bookmarkmanager.add_highlight(
+ self._view.get_current_page(), selection_tuple)
+ else:
+ self._bookmarkmanager.del_highlight(
+ self._view.get_current_page(), old_highlight_found)
+
+ self._view.show_highlights(self._bookmarkmanager.get_highlights(
+ self._view.get_current_page()))
+
def __prev_bookmark_activate_cb(self, menuitem):
page = self._view.get_current_page()
- bookmarkmanager = self._sidebar.get_bookmarkmanager()
- prev_bookmark = bookmarkmanager.get_prev_bookmark_for_page(page)
+ prev_bookmark = self._bookmarkmanager.get_prev_bookmark_for_page(page)
if prev_bookmark is not None:
self._view.set_current_page(prev_bookmark.page_no)
def __next_bookmark_activate_cb(self, menuitem):
page = self._view.get_current_page()
- bookmarkmanager = self._sidebar.get_bookmarkmanager()
- next_bookmark = bookmarkmanager.get_next_bookmark_for_page(page)
+ next_bookmark = self._bookmarkmanager.get_next_bookmark_for_page(page)
if next_bookmark is not None:
self._view.set_current_page(next_bookmark.page_no)
@@ -452,6 +488,10 @@ class ReadActivity(activity.Activity):
self._sidebar.is_showing_local_bookmark()
self._bookmarker.handler_unblock(self._bookmarker_toggle_handler_id)
+ tuples_list = self._bookmarkmanager.get_highlights(
+ self._view.get_current_page())
+ self._view.show_highlights(tuples_list)
+
def _update_nav_buttons(self):
current_page = self._view.get_current_page()
self._back_button.props.sensitive = current_page > 0
@@ -766,17 +806,13 @@ class ReadActivity(activity.Activity):
self._topbar.set_view(self._view)
filehash = get_md5(filepath)
- self._sidebar.set_bookmarkmanager(filehash)
-
+ self._bookmarkmanager = BookmarkManager(filehash)
+ self._sidebar.set_bookmarkmanager(self._bookmarkmanager)
self._update_nav_buttons()
self._update_toc()
-
self._view.connect_page_changed_handler(self.__page_changed_cb)
-
-
self._view.load_metadata(self)
-
- self._view_toolbar._update_zoom_buttons()
+ self._update_toolbars()
self._edit_toolbar._search_entry.props.text = \
self.metadata.get('Read_search', '')
@@ -793,6 +829,11 @@ class ReadActivity(activity.Activity):
except Exception, e:
_logger.debug('Sharing failed: %s', e)
+ def _update_toolbars(self):
+ self._view_toolbar._update_zoom_buttons()
+ if not self._view.can_highlight():
+ self._highlight_item.hide()
+
def _share_document(self):
"""Share the document."""
# FIXME: should ideally have the fileserver listen on a Unix socket
@@ -857,6 +898,33 @@ class ReadActivity(activity.Activity):
def _view_selection_changed_cb(self, view):
self._edit_toolbar.copy.props.sensitive = view.get_has_selection()
+ if self._view.can_highlight():
+ # Verify if the selection already exist or the cursor
+ # is in a highlighted area
+ cursor_position = self._view.get_cursor_position()
+ logging.debug('cursor position %d' % cursor_position)
+ selection_tuple = self._view.get_selection_bounds()
+ tuples_list = self._bookmarkmanager.get_highlights( \
+ self._view.get_current_page())
+ in_bounds = False
+ for highlight_tuple in tuples_list:
+ logging.debug('control tuple %s' % str(highlight_tuple))
+ if selection_tuple:
+ if selection_tuple[0] >= highlight_tuple[0] and \
+ selection_tuple[1] <= highlight_tuple[1]:
+ in_bounds = True
+ break
+ if cursor_position >= highlight_tuple[0] and \
+ cursor_position <= highlight_tuple[1]:
+ in_bounds = True
+ break
+
+ self._highlight.props.sensitive = \
+ view.get_has_selection() or in_bounds
+
+ self._highlight.handler_block(self._highlight_id)
+ self._highlight.set_active(in_bounds)
+ self._highlight.handler_unblock(self._highlight_id)
def _edit_toolbar_copy_cb(self, button):
self._view.copy()
diff --git a/readdb.py b/readdb.py
index fe4ef90..f63564f 100644
--- a/readdb.py
+++ b/readdb.py
@@ -17,7 +17,7 @@
import logging
-import os, os.path
+import os
import shutil
import sqlite3
import time
@@ -54,7 +54,8 @@ def _init_db():
shutil.copy(olddbpath, dbpath)
conn = sqlite3.connect(dbpath)
- conn.execute("CREATE TABLE temp_bookmarks AS SELECT md5, page, title 'content', timestamp, user, color, local FROM bookmarks")
+ conn.execute("CREATE TABLE temp_bookmarks AS SELECT md5, page, " + \
+ "title 'content', timestamp, user, color, local FROM bookmarks")
conn.execute("ALTER TABLE bookmarks RENAME TO bookmarks_old")
conn.execute("ALTER TABLE temp_bookmarks RENAME TO bookmarks")
conn.execute("DROP TABLE bookmarks_old")
@@ -67,6 +68,13 @@ def _init_db():
return None
+def _init_db_highlights(conn):
+ conn.execute('CREATE TABLE IF NOT EXISTS HIGHLIGHTS ' +
+ '(md5 TEXT, page INTEGER, ' +
+ 'init_pos INTEGER, end_pos INTEGER)')
+ conn.commit()
+
+
class BookmarkManager:
def __init__(self, filehash):
@@ -77,40 +85,46 @@ class BookmarkManager:
assert dbpath != None
self._conn = sqlite3.connect(dbpath)
+ _init_db_highlights(self._conn)
+
self._conn.text_factory = lambda x: unicode(x, "utf-8", "ignore")
self._bookmarks = []
self._populate_bookmarks()
+ self._highlights = {0: []}
+ self._populate_highlights()
+
+ client = gconf.client_get_default()
+ self._user = client.get_string("/desktop/sugar/user/nick")
+ self._color = client.get_string("/desktop/sugar/user/color")
def add_bookmark(self, page, content, local=1):
# locale = 0 means that this is a bookmark originally
# created by the person who originally shared the file
timestamp = time.time()
- client = gconf.client_get_default()
- user = client.get_string("/desktop/sugar/user/nick")
- color = client.get_string("/desktop/sugar/user/color")
-
- t = (self._filehash, page, content, timestamp, user, color, local)
- self._conn.execute('insert into bookmarks values (?, ?, ?, ?, ?, ?, ?)', t)
+ t = (self._filehash, page, content, timestamp, self._user, \
+ self._color, local)
+ self._conn.execute('insert into bookmarks values ' + \
+ '(?, ?, ?, ?, ?, ?, ?)', t)
self._conn.commit()
self._resync_bookmark_cache()
def del_bookmark(self, page):
- client = gconf.client_get_default()
- user = client.get_string("/desktop/sugar/user/nick")
-
# We delete only the locally made bookmark
- t = (self._filehash, page, user)
- self._conn.execute('delete from bookmarks where md5=? and page=? and user=?', t)
+ t = (self._filehash, page, self._user)
+ self._conn.execute('delete from bookmarks ' + \
+ 'where md5=? and page=? and user=?', t)
self._conn.commit()
self._resync_bookmark_cache()
def _populate_bookmarks(self):
- # TODO: Figure out if caching the entire set of bookmarks is a good idea or not
- rows = self._conn.execute('select * from bookmarks where md5=? order by page', (self._filehash, ))
+ # TODO: Figure out if caching the entire set of bookmarks
+ # is a good idea or not
+ rows = self._conn.execute('select * from bookmarks ' + \
+ 'where md5=? order by page', (self._filehash, ))
for row in rows:
self._bookmarks.append(Bookmark(row))
@@ -155,3 +169,40 @@ class BookmarkManager:
return bookmark
return None
+
+ def get_highlights(self, page):
+ try:
+ return self._highlights[page]
+ except KeyError:
+ self._highlights[page] = []
+ return self._highlights[page]
+
+ def add_highlight(self, page, highlight_tuple):
+ logging.error('Adding hg page %d %s' % (page, highlight_tuple))
+ self.get_highlights(page).append(highlight_tuple)
+
+ t = (self._filehash, page, highlight_tuple[0],
+ highlight_tuple[1])
+ self._conn.execute('insert into highlights values ' + \
+ '(?, ?, ?, ?)', t)
+ self._conn.commit()
+
+ def del_highlight(self, page, highlight_tuple):
+ self._highlights[page].remove(highlight_tuple)
+ t = (self._filehash, page, highlight_tuple[0], \
+ highlight_tuple[1])
+ self._conn.execute('delete from highlights ' + \
+ 'where md5=? and page=? and init_pos=? and end_pos=?', \
+ t)
+ self._conn.commit()
+
+ def _populate_highlights(self):
+ rows = self._conn.execute('select * from highlights ' + \
+ 'where md5=? order by page', (self._filehash, ))
+ for row in rows:
+ # md5 = row[0]
+ page = row[1]
+ init_pos = row[2]
+ end_pos = row[3]
+ highlight_tuple = [init_pos, end_pos]
+ self.get_highlights(page).append(highlight_tuple)
diff --git a/readsidebar.py b/readsidebar.py
index c22d462..041b478 100644
--- a/readsidebar.py
+++ b/readsidebar.py
@@ -145,8 +145,8 @@ class Sidebar(gtk.EventBox):
self._is_showing_local_bookmark = False
- def set_bookmarkmanager(self, filehash):
- self._bookmark_manager = BookmarkManager(filehash)
+ def set_bookmarkmanager(self, bookmark_manager):
+ self._bookmark_manager = bookmark_manager
def get_bookmarkmanager(self):
return (self._bookmark_manager)
diff --git a/textadapter.py b/textadapter.py
index c3709e5..a82c153 100644
--- a/textadapter.py
+++ b/textadapter.py
@@ -51,6 +51,11 @@ class TextViewer(gobject.GObject):
self.font_zoom_relation = self._zoom / self._font_size
self._current_page = 0
+ self.highlight_tag = self.textview.get_buffer().create_tag()
+ self.highlight_tag.set_property('underline', 'single')
+ self.highlight_tag.set_property('foreground', 'black')
+ self.highlight_tag.set_property('background', 'yellow')
+
def load_document(self, file_path):
self._etext_file = open(file_path.replace('file://', ''), 'r')
@@ -88,6 +93,30 @@ class TextViewer(gobject.GObject):
label_text = label_text + '\n\n\n'
textbuffer.set_text(label_text)
+ def can_highlight(self):
+ return True
+
+ def get_selection_bounds(self):
+ if self.textview.get_buffer().get_selection_bounds():
+ begin, end = self.textview.get_buffer().get_selection_bounds()
+ return [begin.get_offset(), end.get_offset()]
+ else:
+ return []
+
+ def get_cursor_position(self):
+ insert_mark = self.textview.get_buffer().get_insert()
+ return self.textview.get_buffer().get_iter_at_mark( \
+ insert_mark).get_offset()
+
+ def show_highlights(self, tuples_list):
+ textbuffer = self.textview.get_buffer()
+ bounds = textbuffer.get_bounds()
+ textbuffer.remove_all_tags(bounds[0], bounds[1])
+ for highlight_tuple in tuples_list:
+ iterStart = textbuffer.get_iter_at_offset(highlight_tuple[0])
+ iterEnd = textbuffer.get_iter_at_offset(highlight_tuple[1])
+ textbuffer.apply_tag(self.highlight_tag, iterStart, iterEnd)
+
def connect_page_changed_handler(self, handler):
self.connect('page-changed', handler)
@@ -148,7 +177,7 @@ class TextViewer(gobject.GObject):
def get_current_file(self):
pass
- def update_metadata(self):
+ def update_metadata(self, activity):
pass
def copy(self):