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.
Gonzalo Odiard
13 years ago
43 | 43 | pass |
44 | 44 | |
45 | 45 | def can_zoom_to_width(self): |
46 | return False | |
47 | ||
48 | def can_highlight(self): | |
46 | 49 | return False |
47 | 50 | |
48 | 51 | def connect_zoom_handler(self, handler): |
108 | 108 | self._model.props.sizing_mode) |
109 | 109 | self.metadata['Read_sizing_mode'] = "fit-width" |
110 | 110 | |
111 | def can_highlight(self): | |
112 | return False | |
113 | ||
111 | 114 | def get_zoom(self): |
112 | 115 | ''' |
113 | 116 | Returns the current zoom level |
47 | 47 | from readtoolbar import EditToolbar, ViewToolbar |
48 | 48 | from readsidebar import Sidebar |
49 | 49 | from readtopbar import TopBar |
50 | ||
50 | from readdb import BookmarkManager | |
51 | 51 | import epubadapter |
52 | 52 | import evinceadapter |
53 | 53 | import textadapter |
232 | 232 | self._bookmarker.show() |
233 | 233 | toolbar_box.toolbar.insert(bookmark_item, -1) |
234 | 234 | bookmark_item.show() |
235 | ||
236 | self._highlight_item = gtk.ToolItem() | |
237 | self._highlight = ToggleToolButton('format-text-underline') | |
238 | self._highlight.set_tooltip(_('Highlight')) | |
239 | self._highlight.props.sensitive = False | |
240 | self._highlight_id = self._highlight.connect('clicked', \ | |
241 | self.__highlight_cb) | |
242 | self._highlight_item.add(self._highlight) | |
243 | toolbar_box.toolbar.insert(self._highlight_item, -1) | |
244 | self._highlight_item.show_all() | |
235 | 245 | |
236 | 246 | separator = gtk.SeparatorToolItem() |
237 | 247 | separator.props.draw = False |
416 | 426 | def __go_forward_page_cb(self, button): |
417 | 427 | self._view.next_page() |
418 | 428 | |
429 | def __highlight_cb(self, button): | |
430 | tuples_list = self._bookmarkmanager.get_highlights( | |
431 | self._view.get_current_page()) | |
432 | selection_tuple = self._view.get_selection_bounds() | |
433 | cursor_position = self._view.get_cursor_position() | |
434 | ||
435 | old_highlight_found = None | |
436 | for compare_tuple in tuples_list: | |
437 | if selection_tuple: | |
438 | if selection_tuple[0] >= compare_tuple[0] and \ | |
439 | selection_tuple[1] <= compare_tuple[1]: | |
440 | old_highlight_found = compare_tuple | |
441 | break | |
442 | if cursor_position >= compare_tuple[0] and \ | |
443 | cursor_position <= compare_tuple[1]: | |
444 | old_highlight_found = compare_tuple | |
445 | break | |
446 | ||
447 | if old_highlight_found == None: | |
448 | self._bookmarkmanager.add_highlight( | |
449 | self._view.get_current_page(), selection_tuple) | |
450 | else: | |
451 | self._bookmarkmanager.del_highlight( | |
452 | self._view.get_current_page(), old_highlight_found) | |
453 | ||
454 | self._view.show_highlights(self._bookmarkmanager.get_highlights( | |
455 | self._view.get_current_page())) | |
456 | ||
419 | 457 | def __prev_bookmark_activate_cb(self, menuitem): |
420 | 458 | page = self._view.get_current_page() |
421 | bookmarkmanager = self._sidebar.get_bookmarkmanager() | |
422 | ||
423 | prev_bookmark = bookmarkmanager.get_prev_bookmark_for_page(page) | |
459 | ||
460 | prev_bookmark = self._bookmarkmanager.get_prev_bookmark_for_page(page) | |
424 | 461 | if prev_bookmark is not None: |
425 | 462 | self._view.set_current_page(prev_bookmark.page_no) |
426 | 463 | |
427 | 464 | def __next_bookmark_activate_cb(self, menuitem): |
428 | 465 | page = self._view.get_current_page() |
429 | bookmarkmanager = self._sidebar.get_bookmarkmanager() | |
430 | ||
431 | next_bookmark = bookmarkmanager.get_next_bookmark_for_page(page) | |
466 | ||
467 | next_bookmark = self._bookmarkmanager.get_next_bookmark_for_page(page) | |
432 | 468 | if next_bookmark is not None: |
433 | 469 | self._view.set_current_page(next_bookmark.page_no) |
434 | 470 | |
450 | 486 | self._bookmarker.props.active = \ |
451 | 487 | self._sidebar.is_showing_local_bookmark() |
452 | 488 | self._bookmarker.handler_unblock(self._bookmarker_toggle_handler_id) |
489 | ||
490 | tuples_list = self._bookmarkmanager.get_highlights( | |
491 | self._view.get_current_page()) | |
492 | self._view.show_highlights(tuples_list) | |
453 | 493 | |
454 | 494 | def _update_nav_buttons(self): |
455 | 495 | current_page = self._view.get_current_page() |
765 | 805 | self._topbar.set_view(self._view) |
766 | 806 | |
767 | 807 | filehash = get_md5(filepath) |
768 | self._sidebar.set_bookmarkmanager(filehash) | |
769 | ||
808 | self._bookmarkmanager = BookmarkManager(filehash) | |
809 | self._sidebar.set_bookmarkmanager(self._bookmarkmanager) | |
770 | 810 | self._update_nav_buttons() |
771 | 811 | self._update_toc() |
772 | ||
773 | 812 | self._view.connect_page_changed_handler(self.__page_changed_cb) |
774 | ||
775 | ||
776 | 813 | self._view.load_metadata(self) |
777 | ||
778 | self._view_toolbar._update_zoom_buttons() | |
814 | self._update_toolbars() | |
779 | 815 | |
780 | 816 | self._edit_toolbar._search_entry.props.text = \ |
781 | 817 | self.metadata.get('Read_search', '') |
791 | 827 | self._share_document() |
792 | 828 | except Exception, e: |
793 | 829 | _logger.debug('Sharing failed: %s', e) |
830 | ||
831 | def _update_toolbars(self): | |
832 | self._view_toolbar._update_zoom_buttons() | |
833 | if not self._view.can_highlight(): | |
834 | self._highlight_item.hide() | |
794 | 835 | |
795 | 836 | def _share_document(self): |
796 | 837 | """Share the document.""" |
856 | 897 | |
857 | 898 | def _view_selection_changed_cb(self, view): |
858 | 899 | self._edit_toolbar.copy.props.sensitive = view.get_has_selection() |
900 | if self._view.can_highlight(): | |
901 | # Verify if the selection already exist or the cursor | |
902 | # is in a highlighted area | |
903 | cursor_position = self._view.get_cursor_position() | |
904 | logging.debug('cursor position %d' % cursor_position) | |
905 | selection_tuple = self._view.get_selection_bounds() | |
906 | tuples_list = self._bookmarkmanager.get_highlights( \ | |
907 | self._view.get_current_page()) | |
908 | in_bounds = False | |
909 | for highlight_tuple in tuples_list: | |
910 | logging.debug('control tuple %s' % str(highlight_tuple)) | |
911 | if selection_tuple: | |
912 | if selection_tuple[0] >= highlight_tuple[0] and \ | |
913 | selection_tuple[1] <= highlight_tuple[1]: | |
914 | in_bounds = True | |
915 | break | |
916 | if cursor_position >= highlight_tuple[0] and \ | |
917 | cursor_position <= highlight_tuple[1]: | |
918 | in_bounds = True | |
919 | break | |
920 | ||
921 | self._highlight.props.sensitive = \ | |
922 | view.get_has_selection() or in_bounds | |
923 | ||
924 | self._highlight.handler_block(self._highlight_id) | |
925 | self._highlight.set_active(in_bounds) | |
926 | self._highlight.handler_unblock(self._highlight_id) | |
859 | 927 | |
860 | 928 | def _edit_toolbar_copy_cb(self, button): |
861 | 929 | self._view.copy() |
16 | 16 | |
17 | 17 | import logging |
18 | 18 | |
19 | import os, os.path | |
19 | import os | |
20 | 20 | import shutil |
21 | 21 | import sqlite3 |
22 | 22 | import time |
53 | 53 | shutil.copy(olddbpath, dbpath) |
54 | 54 | |
55 | 55 | conn = sqlite3.connect(dbpath) |
56 | conn.execute("CREATE TABLE temp_bookmarks AS SELECT md5, page, title 'content', timestamp, user, color, local FROM bookmarks") | |
56 | conn.execute("CREATE TABLE temp_bookmarks AS SELECT md5, page, " + \ | |
57 | "title 'content', timestamp, user, color, local FROM bookmarks") | |
57 | 58 | conn.execute("ALTER TABLE bookmarks RENAME TO bookmarks_old") |
58 | 59 | conn.execute("ALTER TABLE temp_bookmarks RENAME TO bookmarks") |
59 | 60 | conn.execute("DROP TABLE bookmarks_old") |
66 | 67 | return None |
67 | 68 | |
68 | 69 | |
70 | def _init_db_highlights(conn): | |
71 | conn.execute('CREATE TABLE IF NOT EXISTS HIGHLIGHTS ' + | |
72 | '(md5 TEXT, page INTEGER, ' + | |
73 | 'init_pos INTEGER, end_pos INTEGER)') | |
74 | conn.commit() | |
75 | ||
76 | ||
69 | 77 | class BookmarkManager: |
70 | 78 | |
71 | 79 | def __init__(self, filehash): |
76 | 84 | assert dbpath != None |
77 | 85 | |
78 | 86 | self._conn = sqlite3.connect(dbpath) |
87 | _init_db_highlights(self._conn) | |
88 | ||
79 | 89 | self._conn.text_factory = lambda x: unicode(x, "utf-8", "ignore") |
80 | 90 | |
81 | 91 | self._bookmarks = [] |
82 | 92 | self._populate_bookmarks() |
93 | self._highlights = {0: []} | |
94 | self._populate_highlights() | |
95 | ||
96 | client = gconf.client_get_default() | |
97 | self._user = client.get_string("/desktop/sugar/user/nick") | |
98 | self._color = client.get_string("/desktop/sugar/user/color") | |
83 | 99 | |
84 | 100 | def add_bookmark(self, page, content, local=1): |
85 | 101 | # locale = 0 means that this is a bookmark originally |
86 | 102 | # created by the person who originally shared the file |
87 | 103 | timestamp = time.time() |
88 | client = gconf.client_get_default() | |
89 | user = client.get_string("/desktop/sugar/user/nick") | |
90 | color = client.get_string("/desktop/sugar/user/color") | |
91 | ||
92 | t = (self._filehash, page, content, timestamp, user, color, local) | |
93 | self._conn.execute('insert into bookmarks values (?, ?, ?, ?, ?, ?, ?)', t) | |
104 | t = (self._filehash, page, content, timestamp, self._user, \ | |
105 | self._color, local) | |
106 | self._conn.execute('insert into bookmarks values ' + \ | |
107 | '(?, ?, ?, ?, ?, ?, ?)', t) | |
94 | 108 | self._conn.commit() |
95 | 109 | |
96 | 110 | self._resync_bookmark_cache() |
97 | 111 | |
98 | 112 | def del_bookmark(self, page): |
99 | client = gconf.client_get_default() | |
100 | user = client.get_string("/desktop/sugar/user/nick") | |
101 | ||
102 | 113 | # We delete only the locally made bookmark |
103 | 114 | |
104 | t = (self._filehash, page, user) | |
105 | self._conn.execute('delete from bookmarks where md5=? and page=? and user=?', t) | |
115 | t = (self._filehash, page, self._user) | |
116 | self._conn.execute('delete from bookmarks ' + \ | |
117 | 'where md5=? and page=? and user=?', t) | |
106 | 118 | self._conn.commit() |
107 | 119 | |
108 | 120 | self._resync_bookmark_cache() |
109 | 121 | |
110 | 122 | def _populate_bookmarks(self): |
111 | # TODO: Figure out if caching the entire set of bookmarks is a good idea or not | |
112 | rows = self._conn.execute('select * from bookmarks where md5=? order by page', (self._filehash, )) | |
123 | # TODO: Figure out if caching the entire set of bookmarks | |
124 | # is a good idea or not | |
125 | rows = self._conn.execute('select * from bookmarks ' + \ | |
126 | 'where md5=? order by page', (self._filehash, )) | |
113 | 127 | |
114 | 128 | for row in rows: |
115 | 129 | self._bookmarks.append(Bookmark(row)) |
154 | 168 | return bookmark |
155 | 169 | |
156 | 170 | return None |
171 | ||
172 | def get_highlights(self, page): | |
173 | try: | |
174 | return self._highlights[page] | |
175 | except KeyError: | |
176 | self._highlights[page] = [] | |
177 | return self._highlights[page] | |
178 | ||
179 | def add_highlight(self, page, highlight_tuple): | |
180 | logging.error('Adding hg page %d %s' % (page, highlight_tuple)) | |
181 | self.get_highlights(page).append(highlight_tuple) | |
182 | ||
183 | t = (self._filehash, page, highlight_tuple[0], | |
184 | highlight_tuple[1]) | |
185 | self._conn.execute('insert into highlights values ' + \ | |
186 | '(?, ?, ?, ?)', t) | |
187 | self._conn.commit() | |
188 | ||
189 | def del_highlight(self, page, highlight_tuple): | |
190 | self._highlights[page].remove(highlight_tuple) | |
191 | t = (self._filehash, page, highlight_tuple[0], \ | |
192 | highlight_tuple[1]) | |
193 | self._conn.execute('delete from highlights ' + \ | |
194 | 'where md5=? and page=? and init_pos=? and end_pos=?', \ | |
195 | t) | |
196 | self._conn.commit() | |
197 | ||
198 | def _populate_highlights(self): | |
199 | rows = self._conn.execute('select * from highlights ' + \ | |
200 | 'where md5=? order by page', (self._filehash, )) | |
201 | for row in rows: | |
202 | # md5 = row[0] | |
203 | page = row[1] | |
204 | init_pos = row[2] | |
205 | end_pos = row[3] | |
206 | highlight_tuple = [init_pos, end_pos] | |
207 | self.get_highlights(page).append(highlight_tuple) |
144 | 144 | |
145 | 145 | self._is_showing_local_bookmark = False |
146 | 146 | |
147 | def set_bookmarkmanager(self, filehash): | |
148 | self._bookmark_manager = BookmarkManager(filehash) | |
147 | def set_bookmarkmanager(self, bookmark_manager): | |
148 | self._bookmark_manager = bookmark_manager | |
149 | 149 | |
150 | 150 | def get_bookmarkmanager(self): |
151 | 151 | return (self._bookmark_manager) |
49 | 49 | self._zoom = 100 |
50 | 50 | self.font_zoom_relation = self._zoom / self._font_size |
51 | 51 | self._current_page = 0 |
52 | ||
53 | self.highlight_tag = self.textview.get_buffer().create_tag() | |
54 | self.highlight_tag.set_property('underline', 'single') | |
55 | self.highlight_tag.set_property('foreground', 'black') | |
56 | self.highlight_tag.set_property('background', 'yellow') | |
52 | 57 | |
53 | 58 | def load_document(self, file_path): |
54 | 59 | self._etext_file = open(file_path.replace('file://', ''), 'r') |
86 | 91 | textbuffer = self.textview.get_buffer() |
87 | 92 | label_text = label_text + '\n\n\n' |
88 | 93 | textbuffer.set_text(label_text) |
94 | ||
95 | def can_highlight(self): | |
96 | return True | |
97 | ||
98 | def get_selection_bounds(self): | |
99 | if self.textview.get_buffer().get_selection_bounds(): | |
100 | begin, end = self.textview.get_buffer().get_selection_bounds() | |
101 | return [begin.get_offset(), end.get_offset()] | |
102 | else: | |
103 | return [] | |
104 | ||
105 | def get_cursor_position(self): | |
106 | insert_mark = self.textview.get_buffer().get_insert() | |
107 | return self.textview.get_buffer().get_iter_at_mark( \ | |
108 | insert_mark).get_offset() | |
109 | ||
110 | def show_highlights(self, tuples_list): | |
111 | textbuffer = self.textview.get_buffer() | |
112 | bounds = textbuffer.get_bounds() | |
113 | textbuffer.remove_all_tags(bounds[0], bounds[1]) | |
114 | for highlight_tuple in tuples_list: | |
115 | iterStart = textbuffer.get_iter_at_offset(highlight_tuple[0]) | |
116 | iterEnd = textbuffer.get_iter_at_offset(highlight_tuple[1]) | |
117 | textbuffer.apply_tag(self.highlight_tag, iterStart, iterEnd) | |
89 | 118 | |
90 | 119 | def connect_page_changed_handler(self, handler): |
91 | 120 | self.connect('page-changed', handler) |
147 | 176 | def get_current_file(self): |
148 | 177 | pass |
149 | 178 | |
150 | def update_metadata(self): | |
179 | def update_metadata(self, activity): | |
151 | 180 | pass |
152 | 181 | |
153 | 182 | def copy(self): |