From 568aba1c96ae2bfc0166a2d80ad9a2d7efb08670 Mon Sep 17 00:00:00 2001 From: Sayamindu Dasgupta Date: Sat, 27 Jun 2009 21:54:24 +0000 Subject: Add initial Epub support Everything except search works --- diff --git a/readactivity.py b/readactivity.py index c876e22..ca1fcbd 100644 --- a/readactivity.py +++ b/readactivity.py @@ -36,6 +36,8 @@ from sugar.graphics.objectchooser import ObjectChooser from readtoolbar import EditToolbar, ReadToolbar, ViewToolbar from readsidebar import Sidebar +import epubadapter + _HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager' _HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager' @@ -102,6 +104,7 @@ class ReadActivity(activity.Activity): # if we use evince-2.24 evince.evince_embed_init() + self._epub = False self._document = None self._fileserver = None self._object_id = handle.object_id @@ -111,17 +114,14 @@ class ReadActivity(activity.Activity): _logger.debug('Starting Read...') - self._view = evince.View() - self._view.set_screen_dpi(_get_screen_dpi()) - self._view.connect('notify::has-selection', - self._view_notify_has_selection_cb) + self._view = None self._sidebar = Sidebar() self._sidebar.show() toolbox = activity.ActivityToolbox(self) - self._edit_toolbar = EditToolbar(self._view) + self._edit_toolbar = EditToolbar() self._edit_toolbar.undo.props.visible = False self._edit_toolbar.redo.props.visible = False self._edit_toolbar.separator.props.visible = False @@ -131,11 +131,11 @@ class ReadActivity(activity.Activity): toolbox.add_toolbar(_('Edit'), self._edit_toolbar) self._edit_toolbar.show() - self._read_toolbar = ReadToolbar(self._view, self._sidebar) + self._read_toolbar = ReadToolbar(self._sidebar) toolbox.add_toolbar(_('Read'), self._read_toolbar) self._read_toolbar.show() - self._view_toolbar = ViewToolbar(self._view) + self._view_toolbar = ViewToolbar() self._view_toolbar.connect('needs-update-size', self.__view_toolbar_needs_update_size_cb) self._view_toolbar.connect('go-fullscreen', @@ -146,20 +146,11 @@ class ReadActivity(activity.Activity): self.set_toolbox(toolbox) toolbox.show() - self._scrolled = gtk.ScrolledWindow() - self._scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self._scrolled.props.shadow_type = gtk.SHADOW_NONE - - self._scrolled.add(self._view) - self._view.show() + self._hbox = gtk.HBox() + self._hbox.pack_start(self._sidebar, expand=False, fill=False) - hbox = gtk.HBox() - hbox.pack_start(self._sidebar, expand=False, fill=False) - hbox.pack_start(self._scrolled, expand=True, fill=True) - - self.set_canvas(hbox) - self._scrolled.show() - hbox.show() + self.set_canvas(self._hbox) + self._hbox.show() # Set up for idle suspend self._idle_timer = 0 @@ -316,15 +307,16 @@ class ReadActivity(activity.Activity): self.metadata['Read_zoom'] = str(self._view.props.zoom) - if self._view.props.sizing_mode == evince.SIZING_BEST_FIT: - self.metadata['Read_sizing_mode'] = "best-fit" - elif self._view.props.sizing_mode == evince.SIZING_FREE: - self.metadata['Read_sizing_mode'] = "free" - elif self._view.props.sizing_mode == evince.SIZING_FIT_WIDTH: - self.metadata['Read_sizing_mode'] = "fit-width" - else: - _logger.error("Don't know how to save sizing_mode state '%s'" % - self._view.props.sizing_mode) + if not self._epub: + if self._view.props.sizing_mode == evince.SIZING_BEST_FIT: + self.metadata['Read_sizing_mode'] = "best-fit" + elif self._view.props.sizing_mode == evince.SIZING_FREE: + self.metadata['Read_sizing_mode'] = "free" + elif self._view.props.sizing_mode == evince.SIZING_FIT_WIDTH: + self.metadata['Read_sizing_mode'] = "fit-width" + else: + _logger.error("Don't know how to save sizing_mode state '%s'" % + self._view.props.sizing_mode) self.metadata['Read_sizing_mode'] = "fit-width" self.metadata['Read_search'] = \ @@ -452,13 +444,63 @@ class ReadActivity(activity.Activity): self.watch_for_tubes() gobject.idle_add(self._get_document) + def _setup_evince_viewer(self): + self._view = evince.View() + self._scrolled = gtk.ScrolledWindow() + self._scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self._scrolled.props.shadow_type = gtk.SHADOW_NONE + + self._scrolled.add(self._view) + self._view.show() + + self._hbox.pack_start(self._scrolled, expand=True, fill=True) + + + def _setup_epub_viewer(self): + self._view = epubadapter.View() + self._view.set_screen_dpi(_get_screen_dpi()) + self._view.connect('notify::has-selection', + self._view_notify_has_selection_cb) + + self._hbox.pack_start(self._view, expand=True, fill=True) + self._view.show_all() + + def _setup_evince_viewer(self): + self._view = evince.View() + self._view.set_screen_dpi(_get_screen_dpi()) + self._view.connect('notify::has-selection', + self._view_notify_has_selection_cb) + + self._scrolled = gtk.ScrolledWindow() + self._scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self._scrolled.props.shadow_type = gtk.SHADOW_NONE + + self._scrolled.add(self._view) + self._view.show() + + self._hbox.pack_start(self._scrolled, expand=True, fill=True) + self._scrolled.show() + + def _load_document(self, filepath): """Load the specified document and set up the UI. filepath -- string starting with file:// """ - self._document = evince.factory_get_document(filepath) + mimetype = mime.get_for_file(filepath) + if mimetype == 'application/epub+zip': + self._epub = True + self._setup_epub_viewer() + self._document = epubadapter.EpubDocument(self._view, filepath.replace('file://', '')) + else: + self._setup_evince_viewer() + self._document = evince.factory_get_document(filepath) + + self._view_toolbar.set_view(self._view) + self._edit_toolbar.set_view(self._view) + self._read_toolbar.set_view(self._view) + self._want_document = False self._view.set_document(self._document) self._edit_toolbar.set_document(self._document) @@ -469,33 +511,35 @@ class ReadActivity(activity.Activity): if info and info.title: self.metadata['title'] = info.title - current_page = int(self.metadata.get('Read_current_page', '0')) - self._document.get_page_cache().set_current_page(current_page) - - sizing_mode = self.metadata.get('Read_sizing_mode', 'fit-width') - _logger.debug('Found sizing mode: %s', sizing_mode) - if sizing_mode == "best-fit": - self._view.props.sizing_mode = evince.SIZING_BEST_FIT - self._view.update_view_size(self._scrolled) - elif sizing_mode == "free": - self._view.props.sizing_mode = evince.SIZING_FREE - self._view.props.zoom = float(self.metadata.get('Read_zoom', '1.0')) - _logger.debug('Set zoom to %f', self._view.props.zoom) - elif sizing_mode == "fit-width": - self._view.props.sizing_mode = evince.SIZING_FIT_WIDTH - self._view.update_view_size(self._scrolled) - else: - # this may happen when we get a document from a buddy with a later - # version of Read, for example. - _logger.warning("Unknown sizing_mode state '%s'", sizing_mode) - if self.metadata.get('Read_zoom', None) is not None: - self._view.props.zoom = float(self.metadata['Read_zoom']) + if not self._epub: + sizing_mode = self.metadata.get('Read_sizing_mode', 'fit-width') + _logger.debug('Found sizing mode: %s', sizing_mode) + if sizing_mode == "best-fit": + self._view.props.sizing_mode = evince.SIZING_BEST_FIT + self._view.update_view_size(self._scrolled) + elif sizing_mode == "free": + self._view.props.sizing_mode = evince.SIZING_FREE + self._view.props.zoom = float(self.metadata.get('Read_zoom', '1.0')) + _logger.debug('Set zoom to %f', self._view.props.zoom) + elif sizing_mode == "fit-width": + self._view.props.sizing_mode = evince.SIZING_FIT_WIDTH + self._view.update_view_size(self._scrolled) + else: + # this may happen when we get a document from a buddy with a later + # version of Read, for example. + _logger.warning("Unknown sizing_mode state '%s'", sizing_mode) + if self.metadata.get('Read_zoom', None) is not None: + self._view.props.zoom = float(self.metadata['Read_zoom']) self._view_toolbar._update_zoom_buttons() self._edit_toolbar._search_entry.props.text = \ self.metadata.get('Read_search', '') + current_page = int(self.metadata.get('Read_current_page', '0')) + _logger.debug('Setting page to: %d', current_page) + self._document.get_page_cache().set_current_page(current_page) + # We've got the document, so if we're a shared activity, offer it try: if self.get_shared(): @@ -593,7 +637,8 @@ class ReadActivity(activity.Activity): _logger.debug("Keyname Release: %s, time: %s", keyname, event.time) def __view_toolbar_needs_update_size_cb(self, view_toolbar): - self._view.update_view_size(self._scrolled) + if not self._epub: + self._view.update_view_size(self._scrolled) def __view_toolbar_go_fullscreen_cb(self, view_toolbar): self.fullscreen() diff --git a/readtoolbar.py b/readtoolbar.py index d79c1ed..7240327 100644 --- a/readtoolbar.py +++ b/readtoolbar.py @@ -49,11 +49,10 @@ def get_md5(filename): #FIXME: Should be moved somewhere else class EditToolbar(activity.EditToolbar): __gtype_name__ = 'EditToolbar' - def __init__(self, evince_view): + def __init__(self): activity.EditToolbar.__init__(self) - self._evince_view = evince_view - self._evince_view.find_set_highlight_search(True) + self._evince_view = None self._document = None self._find_job = None @@ -97,6 +96,10 @@ class EditToolbar(activity.EditToolbar): self.insert(self._next, -1) self._next.show() + def set_view(self, view): + self._evince_view = view + self._evince_view.find_set_highlight_search(True) + def set_document(self, document): self._document = document @@ -182,10 +185,10 @@ class EditToolbar(activity.EditToolbar): class ReadToolbar(gtk.Toolbar): __gtype_name__ = 'ReadToolbar' - def __init__(self, evince_view, sidebar): + def __init__(self, sidebar): gtk.Toolbar.__init__(self) - self._evince_view = evince_view + self._evince_view = None self._sidebar = sidebar self._document = None @@ -286,7 +289,10 @@ class ReadToolbar(gtk.Toolbar): self.insert(bookmarkitem, -1) bookmarkitem.show_all() - + + def set_view(self, view): + self._evince_view = view + def set_document(self, document, filepath): filehash = get_md5(filepath) self._document = document @@ -345,7 +351,7 @@ class ReadToolbar(gtk.Toolbar): else: self._sidebar.del_bookmark(page) - def _page_changed_cb(self, page, proxy): + def _page_changed_cb(self, page, proxy = None): self._update_nav_buttons() if hasattr(self._document, 'has_document_links'): if self._document.has_document_links(): @@ -391,11 +397,19 @@ class ReadToolbar(gtk.Toolbar): def _toc_select_active_page_foreach(self, model, path, iter, current_page): link = self._toc_model.get(iter, 1)[0] - if current_page == link.get_page(): - self._navigator.set_active_iter(iter) - return True + if not hasattr(link, 'get_page'): + #FIXME: This needs to be implemented in epubadapter, not here + filepath = self._evince_view.get_current_file() + if filepath.endswith(link): + self._navigator.set_active_iter(iter) + return True else: - return False + if current_page == link.get_page(): + self._navigator.set_active_iter(iter) + return True + + return False + def _toc_select_active_page(self): iter = self._navigator.get_active_iter() @@ -403,9 +417,14 @@ class ReadToolbar(gtk.Toolbar): current_link = self._toc_model.get(iter, 1)[0] current_page = self._document.get_page_cache().get_current_page() - if current_link.get_page() == current_page: - # Nothing to do - return + + if not hasattr(current_link, 'get_page'): + filepath = self._evince_view.get_current_file() + if filepath is None or filepath.endswith(current_link): + return + else: + if current_link.get_page() == current_page: + return self._navigator.handler_block(self.__navigator_changed_handler_id) self._toc_model.foreach(self._toc_select_active_page_foreach, current_page) @@ -424,10 +443,10 @@ class ViewToolbar(gtk.Toolbar): ([])) } - def __init__(self, evince_view): + def __init__(self): gtk.Toolbar.__init__(self) - self._evince_view = evince_view + self._evince_view = None self._document = None self._zoom_out = ToolButton('zoom-out') @@ -466,7 +485,6 @@ class ViewToolbar(gtk.Toolbar): self._zoom_spin = gtk.SpinButton() self._zoom_spin.set_range(5.409, 400) self._zoom_spin.set_increments(1, 10) - self._zoom_spin.props.value = self._evince_view.props.zoom * 100 self._zoom_spin_notify_value_handler = self._zoom_spin.connect( 'notify::value', self._zoom_spin_notify_value_cb) tool_item.add(self._zoom_spin) @@ -479,11 +497,6 @@ class ViewToolbar(gtk.Toolbar): self.insert(tool_item_zoom_perc_label, -1) tool_item_zoom_perc_label.show() - self._view_notify_zoom_handler = self._evince_view.connect( - 'notify::zoom', self._view_notify_zoom_cb) - - self._update_zoom_buttons() - spacer = gtk.SeparatorToolItem() spacer.props.draw = False self.insert(spacer, -1) @@ -495,10 +508,24 @@ class ViewToolbar(gtk.Toolbar): self.insert(self._fullscreen, -1) self._fullscreen.show() + self._view_notify_zoom_handler = None + + def set_view(self, view): + self._evince_view = view + self._zoom_spin.props.value = self._evince_view.props.zoom * 100 + self._view_notify_zoom_handler = self._evince_view.connect( + 'notify::zoom', self._view_notify_zoom_cb) + + self._update_zoom_buttons() + + def _zoom_spin_notify_value_cb(self, zoom_spin, pspec): + if not self._view_notify_zoom_handler: + return self._evince_view.disconnect(self._view_notify_zoom_handler) try: - self._evince_view.props.sizing_mode = evince.SIZING_FREE + if hasattr(self._evince_view.props, 'sizing_mode'): + self._evince_view.props.sizing_mode = evince.SIZING_FREE self._evince_view.props.zoom = zoom_spin.props.value / 100.0 finally: self._view_notify_zoom_handler = self._evince_view.connect( @@ -513,7 +540,8 @@ class ViewToolbar(gtk.Toolbar): 'notify::value', self._zoom_spin_notify_value_cb) def zoom_in(self): - self._evince_view.props.sizing_mode = evince.SIZING_FREE + if hasattr(self._evince_view.props, 'sizing_mode'): + self._evince_view.props.sizing_mode = evince.SIZING_FREE self._evince_view.zoom_in() self._update_zoom_buttons() @@ -521,7 +549,8 @@ class ViewToolbar(gtk.Toolbar): self.zoom_in() def zoom_out(self): - self._evince_view.props.sizing_mode = evince.SIZING_FREE + if hasattr(self._evince_view.props, 'sizing_mode'): + self._evince_view.props.sizing_mode = evince.SIZING_FREE self._evince_view.zoom_out() self._update_zoom_buttons() @@ -529,7 +558,8 @@ class ViewToolbar(gtk.Toolbar): self.zoom_out() def zoom_to_width(self): - self._evince_view.props.sizing_mode = evince.SIZING_FIT_WIDTH + if hasattr(self._evince_view.props, 'sizing_mode'): + self._evince_view.props.sizing_mode = evince.SIZING_FIT_WIDTH self.emit('needs-update-size') self._update_zoom_buttons() @@ -541,12 +571,14 @@ class ViewToolbar(gtk.Toolbar): self._zoom_out.props.sensitive = self._evince_view.can_zoom_out() def _zoom_to_fit_menu_item_activate_cb(self, menu_item): - self._evince_view.props.sizing_mode = evince.SIZING_BEST_FIT + if hasattr(self._evince_view.props, 'sizing_mode'): #XXX + self._evince_view.props.sizing_mode = evince.SIZING_BEST_FIT self.emit('needs-update-size') self._update_zoom_buttons() def _actual_size_menu_item_activate_cb(self, menu_item): - self._evince_view.props.sizing_mode = evince.SIZING_FREE + if hasattr(self._evince_view.props, 'sizing_mode'): + self._evince_view.props.sizing_mode = evince.SIZING_FREE self._evince_view.props.zoom = 1.0 self._update_zoom_buttons() -- cgit v0.9.1