diff --git a/.gitignore b/.gitignore
index e7f7ec6..1eab28e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,3 @@
locale
MANIFEST
dist/
-epubview/.svn/
diff --git a/activity/activity.info b/activity/activity.info
index 31a0dba..4b68ae8 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -4,7 +4,7 @@
icon = activity-read
exec = sugar-activity readactivity.ReadActivity
activity_version = 118
-mime_types = application/pdf;image/vnd.djvu;image/x.djvu;image/tiff;application/epub+zip;text/plain;application/zip;application/x-cbz
+mime_types = application/pdf;image/vnd.djvu;image/x.djvu;image/tiff;text/plain;application/zip;application/x-cbz
license = GPLv2+
summary = Use this activity when you are ready to read! Remember to flip your computer around to feel like you are really holding a book!
categories = language documents media system
diff --git a/activity/mimetypes.xml b/activity/mimetypes.xml
deleted file mode 100644
index 5c27572..0000000
--- a/activity/mimetypes.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- Epub document
-
-
-
diff --git a/epubadapter.py b/epubadapter.py
deleted file mode 100644
index c6dcfd3..0000000
--- a/epubadapter.py
+++ /dev/null
@@ -1,309 +0,0 @@
-from gi.repository import GObject
-import logging
-
-import epubview
-
-# import speech
-
-from cStringIO import StringIO
-
-_logger = logging.getLogger('read-activity')
-
-
-class EpubViewer(epubview.EpubView):
-
- def __init__(self):
- epubview.EpubView.__init__(self)
-
- def setup(self, activity):
- self.set_screen_dpi(activity.dpi)
- self.connect('selection-changed',
- activity._view_selection_changed_cb)
-
- activity._hbox.pack_start(self, True, True, 0)
- self.show_all()
- self._modified_files = []
-
- # text to speech initialization
- self.current_word = 0
- self.word_tuples = []
-
- def load_document(self, file_path):
- self.set_document(EpubDocument(self, file_path.replace('file://', '')))
- # speech.highlight_cb = self.highlight_next_word
- # speech.reset_cb = self.reset_text_to_speech
- # speech.end_text_cb = self.get_more_text
-
- def load_metadata(self, activity):
-
- self.metadata = activity.metadata
-
- if not self.metadata['title_set_by_user'] == '1':
- title = self._epub._info._get_title()
- if title:
- self.metadata['title'] = title
- if 'Read_zoom' in self.metadata:
- try:
- logging.error('Loading zoom %s', self.metadata['Read_zoom'])
- self.set_zoom(float(self.metadata['Read_zoom']))
- except:
- pass
-
- def update_metadata(self, activity):
- self.metadata = activity.metadata
- self.metadata['Read_zoom'] = self.get_zoom()
-
- def zoom_to_width(self):
- pass
-
- def zoom_to_best_fit(self):
- pass
-
- def zoom_to_actual_size(self):
- pass
-
- def can_zoom_to_width(self):
- return False
-
- def can_highlight(self):
- return True
-
- def show_highlights(self, page):
- # we save the highlights in the page as html
- pass
-
- def toggle_highlight(self, highlight):
- self._view.set_editable(True)
-
- if highlight:
- self._view.execute_script(
- 'document.execCommand("backColor", false, "yellow");')
- else:
- # need remove the highlight nodes
- js = """
- var selObj = window.getSelection();
- var range = selObj.getRangeAt(0);
- var node = range.startContainer;
- while (node.parentNode != null) {
- if (node.localName == "span") {
- if (node.hasAttributes()) {
- var attrs = node.attributes;
- for(var i = attrs.length - 1; i >= 0; i--) {
- if (attrs[i].name == "style" &&
- attrs[i].value == "background-color: yellow;") {
- node.removeAttribute("style");
- break;
- };
- };
- };
- };
- node = node.parentNode;
- };"""
- self._view.execute_script(js)
-
- self._view.set_editable(False)
- # mark the file as modified
- current_file = self.get_current_file()
- logging.error('file %s was modified', current_file)
- if current_file not in self._modified_files:
- self._modified_files.append(current_file)
- GObject.idle_add(self._save_page)
-
- def _save_page(self):
- oldtitle = self._view.get_title()
- self._view.execute_script(
- "document.title=document.documentElement.innerHTML;")
- html = self._view.get_title()
- file_path = self.get_current_file().replace('file:///', '/')
- logging.error(html)
- with open(file_path, 'w') as fd:
- header = """
-
- """
- fd.write(header)
- fd.write(html)
- fd.write('')
- self._view.execute_script('document.title=%s;' % oldtitle)
-
- def save(self, file_path):
- if self._modified_files:
- self._epub.write(file_path)
- return True
-
- return False
-
- def in_highlight(self):
- # Verify if the selection already exist or the cursor
- # is in a highlighted area
- page_title = self._view.get_title()
- js = """
- var selObj = window.getSelection();
- var range = selObj.getRangeAt(0);
- var node = range.startContainer;
- var onHighlight = false;
- while (node.parentNode != null) {
- if (node.localName == "span") {
- if (node.hasAttributes()) {
- var attrs = node.attributes;
- for(var i = attrs.length - 1; i >= 0; i--) {
- if (attrs[i].name == "style" &&
- attrs[i].value == "background-color: yellow;") {
- onHighlight = true;
- };
- };
- };
- };
- node = node.parentNode;
- };
- document.title=onHighlight;"""
- self._view.execute_script(js)
- on_highlight = self._view.get_title() == 'true'
- self._view.execute_script('document.title = "%s";' % page_title)
- # the second parameter is only used in the text backend
- return on_highlight, None
-
- def can_do_text_to_speech(self):
- return False
-
- def can_rotate(self):
- return False
-
- def get_marked_words(self):
- "Adds a mark between each word of text."
- i = self.current_word
- file_str = StringIO()
- file_str.write(' ')
- end_range = i + 40
- if end_range > len(self.word_tuples):
- end_range = len(self.word_tuples)
- for word_tuple in self.word_tuples[self.current_word:end_range]:
- file_str.write('' +
- word_tuple[2].encode('utf-8'))
- i = i + 1
- self.current_word = i
- file_str.write('')
- return file_str.getvalue()
-
- def get_more_text(self):
- pass
- """
- if self.current_word < len(self.word_tuples):
- speech.stop()
- more_text = self.get_marked_words()
- speech.play(more_text)
- else:
- if speech.reset_buttons_cb is not None:
- speech.reset_buttons_cb()
- """
-
- def reset_text_to_speech(self):
- self.current_word = 0
-
- def highlight_next_word(self, word_count):
- pass
- """
- TODO: disabled because javascript can't be executed
- with the velocity needed
- self.current_word = word_count
- self._view.highlight_next_word()
- return True
- """
-
- def connect_zoom_handler(self, handler):
- self._zoom_handler = handler
- self._view_notify_zoom_handler = \
- self.connect('notify::scale', handler)
- return self._view_notify_zoom_handler
-
- def connect_page_changed_handler(self, handler):
- self.connect('page-changed', handler)
-
- def _try_load_page(self, n):
- if self._ready:
- self._load_page(n)
- return False
- else:
- return True
-
- def set_screen_dpi(self, dpi):
- return
-
- def find_set_highlight_search(self, set_highlight_search):
- self._view.set_highlight_text_matches(set_highlight_search)
-
- def set_current_page(self, n):
- # When the book is being loaded, calling this does not help
- # In such a situation, we go into a loop and try to load the
- # supplied page when the book has loaded completely
- n += 1
- if self._ready:
- self._load_page(n)
- else:
- GObject.timeout_add(200, self._try_load_page, n)
-
- def get_current_page(self):
- return int(self._loaded_page) - 1
-
- def get_current_link(self):
- # the _loaded_filename include all the path,
- # need only the part included in the link
- return self._loaded_filename[len(self._epub._tempdir) + 1:]
-
- def update_toc(self, activity):
- if self._epub.has_document_links():
- activity.show_navigator_button()
- activity.set_navigator_model(self._epub.get_links_model())
- return True
- else:
- return False
-
- def get_link_iter(self, current_link):
- """
- Returns the iter related to a link
- """
- link_iter = self._epub.get_links_model().get_iter_first()
-
- while link_iter is not None and \
- self._epub.get_links_model().get_value(link_iter, 1) \
- != current_link:
- link_iter = self._epub.get_links_model().iter_next(link_iter)
- return link_iter
-
- def find_changed(self, job, page=None):
- self._find_changed(job)
-
- def handle_link(self, link):
- self._load_file(link)
-
- def setup_find_job(self, text, updated_cb):
- self._find_job = JobFind(document=self._epub,
- start_page=0, n_pages=self.get_pagecount(),
- text=text, case_sensitive=False)
- self._find_updated_handler = self._find_job.connect('updated',
- updated_cb)
- return self._find_job, self._find_updated_handler
-
-
-class EpubDocument(epubview.Epub):
-
- def __init__(self, view, docpath):
- epubview.Epub.__init__(self, docpath)
- self._page_cache = view
-
- def get_n_pages(self):
- return int(self._page_cache.get_pagecount())
-
- def has_document_links(self):
- return True
-
- def get_links_model(self):
- return self.get_toc_model()
-
-
-class JobFind(epubview.JobFind):
-
- def __init__(self, document, start_page, n_pages, text,
- case_sensitive=False):
- epubview.JobFind.__init__(self, document, start_page, n_pages, text,
- case_sensitive=False)
diff --git a/epubview/__init__.py b/epubview/__init__.py
deleted file mode 100644
index 20d9fc6..0000000
--- a/epubview/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2009 One Laptop Per Child
-# Author: Sayamindu Dasgupta
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-from epub import _Epub as Epub
-from epubview import _View as EpubView
-from jobs import _JobFind as JobFind
diff --git a/epubview/epub.py b/epubview/epub.py
deleted file mode 100644
index 38ccf98..0000000
--- a/epubview/epub.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# Copyright 2009 One Laptop Per Child
-# Author: Sayamindu Dasgupta
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-import zipfile
-import tempfile
-import os
-import xml.etree.ElementTree as etree
-import shutil
-import logging
-
-import navmap
-import epubinfo
-
-
-class _Epub(object):
-
- def __init__(self, _file):
- """
- _file: can be either a path to a file (a string) or a file-like object.
- """
- self._file = _file
- self._zobject = None
- self._opfpath = None
- self._ncxpath = None
- self._basepath = None
- self._tempdir = tempfile.mkdtemp()
-
- if not self._verify():
- print 'Warning: This does not seem to be a valid epub file'
-
- self._get_opf()
- self._get_ncx()
-
- ncxfile = self._zobject.open(self._ncxpath)
- opffile = self._zobject.open(self._opfpath)
- self._navmap = navmap.NavMap(opffile, ncxfile, self._basepath)
-
- opffile = self._zobject.open(self._opfpath)
- self._info = epubinfo.EpubInfo(opffile)
-
- self._unzip()
-
- def _unzip(self):
- # This is broken upto python 2.7
- # self._zobject.extractall(path = self._tempdir)
- orig_cwd = os.getcwd()
- os.chdir(self._tempdir)
- for name in self._zobject.namelist():
- # Some weird zip file entries start with a slash,
- # and we don't want to write to the root directory
- try:
- if name.startswith(os.path.sep):
- name = name[1:]
- if name.endswith(os.path.sep) or name.endswith('\\'):
- os.makedirs(name)
- except:
- logging.error('ERROR unziping %s', name)
- else:
- self._zobject.extract(name)
- os.chdir(orig_cwd)
-
- def _get_opf(self):
- containerfile = self._zobject.open('META-INF/container.xml')
-
- tree = etree.parse(containerfile)
- root = tree.getroot()
-
- r_id = './/{urn:oasis:names:tc:opendocument:xmlns:container}rootfile'
- for element in root.iterfind(r_id):
- if element.get('media-type') == 'application/oebps-package+xml':
- self._opfpath = element.get('full-path')
-
- if self._opfpath.rpartition('/')[0]:
- self._basepath = self._opfpath.rpartition('/')[0] + '/'
- else:
- self._basepath = ''
-
- containerfile.close()
-
- def _get_ncx(self):
- opffile = self._zobject.open(self._opfpath)
-
- tree = etree.parse(opffile)
- root = tree.getroot()
-
- spine = root.find('.//{http://www.idpf.org/2007/opf}spine')
- tocid = spine.get('toc')
-
- for element in root.iterfind('.//{http://www.idpf.org/2007/opf}item'):
- if element.get('id') == tocid:
- self._ncxpath = self._basepath + element.get('href')
-
- opffile.close()
-
- def _verify(self):
- '''
- Method to crudely check to verify that what we
- are dealing with is a epub file or not
- '''
- if isinstance(self._file, basestring):
- if not os.path.exists(self._file):
- return False
-
- self._zobject = zipfile.ZipFile(self._file)
-
- if 'mimetype' not in self._zobject.namelist():
- return False
-
- mtypefile = self._zobject.open('mimetype')
- mimetype = mtypefile.readline()
-
- # Some files seem to have trailing characters
- if not mimetype.startswith('application/epub+zip'):
- return False
-
- return True
-
- def get_toc_model(self):
- '''
- Returns a GtkTreeModel representation of the
- Epub table of contents
- '''
- return self._navmap.get_gtktreestore()
-
- def get_flattoc(self):
- '''
- Returns a flat (linear) list of files to be
- rendered.
- '''
- return self._navmap.get_flattoc()
-
- def get_basedir(self):
- '''
- Returns the base directory where the contents of the
- epub has been unzipped
- '''
- return self._tempdir
-
- def get_info(self):
- '''
- Returns a EpubInfo object title
- '''
- return self._info.title
-
- def write(self, file_path):
- '''Create the ZIP archive.
- The mimetype must be the first file in the archive
- and it must not be compressed.'''
-
- # The EPUB must contain the META-INF and mimetype files at the root, so
- # we'll create the archive in the working directory first
- # and move it later
- current_dir = os.getcwd()
- os.chdir(self._tempdir)
-
- # Open a new zipfile for writing
- epub = zipfile.ZipFile(file_path, 'w')
-
- # Add the mimetype file first and set it to be uncompressed
- epub.write('mimetype', compress_type=zipfile.ZIP_STORED)
-
- # For the remaining paths in the EPUB, add all of their files
- # using normal ZIP compression
- self._scan_dir('.', epub)
-
- epub.close()
- os.chdir(current_dir)
-
- def _scan_dir(self, path, epub_file):
- for p in os.listdir(path):
- logging.error('add file %s', p)
- if os.path.isdir(os.path.join(path, p)):
- self._scan_dir(os.path.join(path, p), epub_file)
- else:
- if p != 'mimetype':
- epub_file.write(
- os.path.join(path, p),
- compress_type=zipfile.ZIP_DEFLATED)
-
- def close(self):
- '''
- Cleans up (closes open zip files and deletes
- uncompressed content of Epub.
- Please call this when a file is being closed or during
- application exit.
- '''
- self._zobject.close()
- shutil.rmtree(self._tempdir)
diff --git a/epubview/epubinfo.py b/epubview/epubinfo.py
deleted file mode 100644
index 5014be4..0000000
--- a/epubview/epubinfo.py
+++ /dev/null
@@ -1,114 +0,0 @@
-import xml.etree.ElementTree as etree
-
-
-class EpubInfo():
-
- # TODO: Cover the entire DC range
-
- def __init__(self, opffile):
- self._tree = etree.parse(opffile)
- self._root = self._tree.getroot()
- self._e_metadata = self._root.find(
- '{http://www.idpf.org/2007/opf}metadata')
-
- self.title = self._get_title()
- self.creator = self._get_creator()
- self.date = self._get_date()
- self.subject = self._get_subject()
- self.source = self._get_source()
- self.rights = self._get_rights()
- self.identifier = self._get_identifier()
- self.language = self._get_language()
- self.summary = self._get_description()
- self.cover_image = self._get_cover_image()
-
- def _get_data(self, tagname):
- element = self._e_metadata.find(tagname)
- return element.text
-
- def _get_title(self):
- try:
- ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}title')
- except AttributeError:
- return None
-
- return ret
-
- def _get_description(self):
- try:
- ret = self._get_data(
- './/{http://purl.org/dc/elements/1.1/}description')
- except AttributeError:
- return None
-
- return ret
-
- def _get_creator(self):
- try:
- ret = self._get_data(
- './/{http://purl.org/dc/elements/1.1/}creator')
- except AttributeError:
- return None
- return ret
-
- def _get_date(self):
- # TODO: iter
- try:
- ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}date')
- except AttributeError:
- return None
-
- return ret
-
- def _get_source(self):
- try:
- ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}source')
- except AttributeError:
- return None
-
- return ret
-
- def _get_rights(self):
- try:
- ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}rights')
- except AttributeError:
- return None
-
- return ret
-
- def _get_identifier(self):
- # TODO: iter
- element = self._e_metadata.find(
- './/{http://purl.org/dc/elements/1.1/}identifier')
-
- if element is not None:
- return {'id': element.get('id'), 'value': element.text}
- else:
- return None
-
- def _get_language(self):
- try:
- ret = self._get_data(
- './/{http://purl.org/dc/elements/1.1/}language')
- except AttributeError:
- return None
-
- return ret
-
- def _get_subject(self):
- try:
- subjectlist = []
- for element in self._e_metadata.iterfind(
- './/{http://purl.org/dc/elements/1.1/}subject'):
- subjectlist.append(element.text)
- except AttributeError:
- return None
-
- return subjectlist
-
- def _get_cover_image(self):
- element = self._e_metadata.find('{http://www.idpf.org/2007/opf}meta')
- if element is not None and element.get('name') == 'cover':
- return element.get('content')
- else:
- return None
diff --git a/epubview/epubview.py b/epubview/epubview.py
deleted file mode 100644
index acf6ceb..0000000
--- a/epubview/epubview.py
+++ /dev/null
@@ -1,712 +0,0 @@
-# Copyright 2009 One Laptop Per Child
-# Author: Sayamindu Dasgupta
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-from gi.repository import Gtk
-from gi.repository import GObject
-from gi.repository import Gdk
-import widgets
-
-import logging
-import os.path
-import math
-import shutil
-
-from jobs import _JobPaginator as _Paginator
-
-LOADING_HTML = '''
-
-
Loading...
-
-'''
-
-
-class _View(Gtk.HBox):
-
- __gproperties__ = {
- 'scale': (GObject.TYPE_FLOAT, 'the zoom level',
- 'the zoom level of the widget',
- 0.5, 4.0, 1.0, GObject.PARAM_READWRITE),
- }
- __gsignals__ = {
- 'page-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE,
- ([int, int])),
- 'selection-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE,
- ([])),
- }
-
- def __init__(self):
- GObject.threads_init()
- Gtk.HBox.__init__(self)
-
- self.connect("destroy", self._destroy_cb)
-
- self._ready = False
- self._paginator = None
- self._loaded_page = -1
- self._file_loaded = True
- # self._old_scrollval = -1
- self._loaded_filename = None
- self._pagecount = -1
- self.__going_fwd = True
- self.__going_back = False
- self.__page_changed = False
- self._has_selection = False
- self.scale = 1.0
- self._epub = None
- self._findjob = None
- self.__in_search = False
- self.__search_fwd = True
- self._filelist = None
- self._internal_link = None
-
- self._sw = Gtk.ScrolledWindow()
- self._view = widgets._WebView()
- self._view.load_string(LOADING_HTML, 'text/html', 'utf-8', '/')
- settings = self._view.get_settings()
- settings.props.default_font_family = 'DejaVu LGC Serif'
- settings.props.enable_plugins = False
- settings.props.default_encoding = 'utf-8'
- self._view.connect('load-finished', self._view_load_finished_cb)
- self._view.connect('scroll-event', self._view_scroll_event_cb)
- self._view.connect('key-press-event', self._view_keypress_event_cb)
- self._view.connect('selection-changed',
- self._view_selection_changed_cb)
- self._view.connect_after('populate-popup',
- self._view_populate_popup_cb)
- self._view.connect('touch-change-page', self.__touch_page_changed_cb)
-
- self._sw.add(self._view)
- self._v_vscrollbar = self._sw.get_vscrollbar()
- self._v_scrollbar_value_changed_cb_id = self._v_vscrollbar.connect(
- 'value-changed', self._v_scrollbar_value_changed_cb)
- self._scrollbar = Gtk.VScrollbar()
- self._scrollbar_change_value_cb_id = self._scrollbar.connect(
- 'change-value', self._scrollbar_change_value_cb)
-
- overlay = Gtk.Overlay()
- hbox = Gtk.HBox()
- overlay.add(hbox)
- hbox.add(self._sw)
-
- self._scrollbar.props.halign = Gtk.Align.END
- self._scrollbar.props.valign = Gtk.Align.FILL
- overlay.add_overlay(self._scrollbar)
-
- self.pack_start(overlay, True, True, 0)
-
- self._view.set_can_default(True)
- self._view.set_can_focus(True)
-
- def map_cp(widget):
- widget.setup_touch()
- widget.disconnect(self._setup_handle)
-
- self._setup_handle = self._view.connect('map', map_cp)
-
- def set_document(self, epubdocumentinstance):
- '''
- Sets document (should be a Epub instance)
- '''
- self._epub = epubdocumentinstance
- GObject.idle_add(self._paginate)
-
- def do_get_property(self, property):
- if property.name == 'has-selection':
- return self._has_selection
- elif property.name == 'scale':
- return self.scale
- else:
- raise AttributeError('unknown property %s' % property.name)
-
- def do_set_property(self, property, value):
- if property.name == 'scale':
- self.__set_zoom(value)
- else:
- raise AttributeError('unknown property %s' % property.name)
-
- def get_has_selection(self):
- '''
- Returns True if any part of the content is selected
- '''
- return self._view.can_copy_clipboard()
-
- def get_zoom(self):
- '''
- Returns the current zoom level
- '''
- return self.get_property('scale') * 100.0
-
- def set_zoom(self, value):
- '''
- Sets the current zoom level
- '''
- scrollbar_pos = self.get_vertical_pos()
- self._view.set_zoom_level(value / 100.0)
- self.set_vertical_pos(scrollbar_pos)
-
- def _get_scale(self):
- '''
- Returns the current zoom level
- '''
- return self.get_property('scale')
-
- def _set_scale(self, value):
- '''
- Sets the current zoom level
- '''
- self.set_property('scale', value)
-
- def zoom_in(self):
- '''
- Zooms in (increases zoom level by 0.1)
- '''
- if self.can_zoom_in():
- scrollbar_pos = self.get_vertical_pos()
- self._set_scale(self._get_scale() + 0.1)
- self.set_vertical_pos(scrollbar_pos)
- return True
- else:
- return False
-
- def zoom_out(self):
- '''
- Zooms out (decreases zoom level by 0.1)
- '''
- if self.can_zoom_out():
- scrollbar_pos = self.get_vertical_pos()
- self._set_scale(self._get_scale() - 0.1)
- self.set_vertical_pos(scrollbar_pos)
- return True
- else:
- return False
-
- def get_vertical_pos(self):
- """
- Used to save the scrolled position and restore when needed
- """
- return self._v_vscrollbar.get_adjustment().get_value()
-
- def set_vertical_pos(self, position):
- """
- Used to save the scrolled position and restore when needed
- """
- self._v_vscrollbar.get_adjustment().set_value(position)
-
- def can_zoom_in(self):
- '''
- Returns True if it is possible to zoom in further
- '''
- if self.scale < 4:
- return True
- else:
- return False
-
- def can_zoom_out(self):
- '''
- Returns True if it is possible to zoom out further
- '''
- if self.scale > 0.5:
- return True
- else:
- return False
-
- def get_current_page(self):
- '''
- Returns the currently loaded page
- '''
- return self._loaded_page
-
- def get_current_file(self):
- '''
- Returns the currently loaded XML file
- '''
- # return self._loaded_filename
- if self._paginator:
- return self._paginator.get_file_for_pageno(self._loaded_page)
- else:
- return None
-
- def get_pagecount(self):
- '''
- Returns the pagecount of the loaded file
- '''
- return self._pagecount
-
- def set_current_page(self, n):
- '''
- Loads page number n
- '''
- if n < 1 or n > self._pagecount:
- return False
- self._load_page(n)
- return True
-
- def next_page(self):
- '''
- Loads next page if possible
- Returns True if transition to next page is possible and done
- '''
- if self._loaded_page == self._pagecount:
- return False
- self._load_next_page()
- return True
-
- def previous_page(self):
- '''
- Loads previous page if possible
- Returns True if transition to previous page is possible and done
- '''
- if self._loaded_page == 1:
- return False
- self._load_prev_page()
- return True
-
- def scroll(self, scrolltype, horizontal):
- '''
- Scrolls through the pages.
- Scrolling is horizontal if horizontal is set to True
- Valid scrolltypes are:
- Gtk.ScrollType.PAGE_BACKWARD, Gtk.ScrollType.PAGE_FORWARD,
- Gtk.ScrollType.STEP_BACKWARD, Gtk.ScrollType.STEP_FORWARD
- Gtk.ScrollType.STEP_START and Gtk.ScrollType.STEP_STOP
- '''
- if scrolltype == Gtk.ScrollType.PAGE_BACKWARD:
- self.__going_back = True
- self.__going_fwd = False
- if not self._do_page_transition():
- self._view.move_cursor(Gtk.MovementStep.PAGES, -1)
- elif scrolltype == Gtk.ScrollType.PAGE_FORWARD:
- self.__going_back = False
- self.__going_fwd = True
- if not self._do_page_transition():
- self._view.move_cursor(Gtk.MovementStep.PAGES, 1)
- elif scrolltype == Gtk.ScrollType.STEP_BACKWARD:
- self.__going_fwd = False
- self.__going_back = True
- if not self._do_page_transition():
- self._view.move_cursor(Gtk.MovementStep.DISPLAY_LINES, -1)
- elif scrolltype == Gtk.ScrollType.STEP_FORWARD:
- self.__going_fwd = True
- self.__going_back = False
- if not self._do_page_transition():
- self._view.move_cursor(Gtk.MovementStep.DISPLAY_LINES, 1)
- elif scrolltype == Gtk.ScrollType.START:
- self.__going_back = True
- self.__going_fwd = False
- if not self._do_page_transition():
- self.set_current_page(1)
- elif scrolltype == Gtk.ScrollType.END:
- self.__going_back = False
- self.__going_fwd = True
- if not self._do_page_transition():
- self.set_current_page(self._pagecount - 1)
- else:
- print ('Got unsupported scrolltype %s' % str(scrolltype))
-
- def __touch_page_changed_cb(self, widget, forward):
- if forward:
- self.scroll(Gtk.ScrollType.PAGE_FORWARD, False)
- else:
- self.scroll(Gtk.ScrollType.PAGE_BACKWARD, False)
-
- def copy(self):
- '''
- Copies the current selection to clipboard.
- '''
- self._view.copy_clipboard()
-
- def find_next(self):
- '''
- Highlights the next matching item for current search
- '''
- self._view.grab_focus()
-
- if self._view.search_text(self._findjob.get_search_text(),
- self._findjob.get_case_sensitive(),
- True, False):
- return
- else:
- path = os.path.join(self._epub.get_basedir(),
- self._findjob.get_next_file())
- self.__in_search = True
- self.__search_fwd = True
- self._load_file(path)
-
- def find_previous(self):
- '''
- Highlights the previous matching item for current search
- '''
- self._view.grab_focus()
-
- if self._view.search_text(self._findjob.get_search_text(),
- self._findjob.get_case_sensitive(),
- False, False):
- return
- else:
- path = os.path.join(self._epub.get_basedir(),
- self._findjob.get_prev_file())
- self.__in_search = True
- self.__search_fwd = False
- self._load_file(path)
-
- def _find_changed(self, job):
- self._view.grab_focus()
- self._findjob = job
- self._mark_found_text()
- self.find_next()
-
- def _mark_found_text(self):
- self._view.unmark_text_matches()
- self._view.mark_text_matches(
- self._findjob.get_search_text(),
- case_sensitive=self._findjob.get_case_sensitive(), limit=0)
- self._view.set_highlight_text_matches(True)
-
- def __set_zoom(self, value):
- self._view.set_zoom_level(value)
- self.scale = value
-
- def _view_populate_popup_cb(self, view, menu):
- menu.destroy() # HACK
- return
-
- def _view_selection_changed_cb(self, view):
- self.emit('selection-changed')
-
- def _view_keypress_event_cb(self, view, event):
- name = Gdk.keyval_name(event.keyval)
- if name == 'Page_Down' or name == 'Down':
- self.__going_back = False
- self.__going_fwd = True
- elif name == 'Page_Up' or name == 'Up':
- self.__going_back = True
- self.__going_fwd = False
-
- self._do_page_transition()
-
- def _view_scroll_event_cb(self, view, event):
- if event.direction == Gdk.ScrollDirection.DOWN:
- self.__going_back = False
- self.__going_fwd = True
- elif event.direction == Gdk.ScrollDirection.UP:
- self.__going_back = True
- self.__going_fwd = False
-
- self._do_page_transition()
-
- def _do_page_transition(self):
- if self.__going_fwd:
- if self._v_vscrollbar.get_value() >= \
- self._v_vscrollbar.props.adjustment.props.upper - \
- self._v_vscrollbar.props.adjustment.props.page_size:
- self._load_page(self._loaded_page + 1)
- return True
- elif self.__going_back:
- if self._v_vscrollbar.get_value() == \
- self._v_vscrollbar.props.adjustment.props.lower:
- self._load_page(self._loaded_page - 1)
- return True
-
- return False
-
- def _view_load_finished_cb(self, v, frame):
-
- self._file_loaded = True
- filename = self._view.props.uri.replace('file://', '')
- if os.path.exists(filename.replace('xhtml', 'xml')):
- # Hack for making javascript work
- filename = filename.replace('xhtml', 'xml')
-
- filename = filename.split('#')[0] # Get rid of anchors
-
- if self._loaded_page < 1 or filename is None:
- return False
-
- self._loaded_filename = filename
-
- remfactor = self._paginator.get_remfactor_for_file(filename)
- pages = self._paginator.get_pagecount_for_file(filename)
- extra = int(math.ceil(
- remfactor * self._view.get_page_height() / (pages - remfactor)))
- if extra > 0:
- self._view.add_bottom_padding(extra)
-
- if self.__in_search:
- self._mark_found_text()
- self._view.search_text(self._findjob.get_search_text(),
- self._findjob.get_case_sensitive(),
- self.__search_fwd, False)
- self.__in_search = False
- else:
- if self.__going_back:
- # We need to scroll to the last page
- self._scroll_page_end()
- else:
- self._scroll_page()
-
- # process_file = True
- if self._internal_link is not None:
- self._view.go_to_link(self._internal_link)
- vertical_pos = \
- self._view.get_vertical_position_element(self._internal_link)
- # set the page number based in the vertical position
- initial_page = self._paginator.get_base_pageno_for_file(filename)
- self._loaded_page = initial_page + int(
- vertical_pos / self._paginator.get_single_page_height())
-
- # There are epub files, created with Calibre,
- # where the link in the index points to the end of the previos
- # file to the needed chapter.
- # if the link is at the bottom of the page, we open the next file
- one_page_height = self._paginator.get_single_page_height()
- self._internal_link = None
- if vertical_pos > self._view.get_page_height() - one_page_height:
- logging.error('bottom page link, go to next file')
- next_file = self._paginator.get_next_filename(filename)
- if next_file is not None:
- logging.error('load next file %s', next_file)
- self.__in_search = False
- self.__going_back = False
- # process_file = False
- GObject.idle_add(self._load_file, next_file)
-
-# if process_file:
-# # prepare text to speech
-# html_file = open(self._loaded_filename)
-# soup = BeautifulSoup.BeautifulSoup(html_file)
-# body = soup.find('body')
-# tags = body.findAll(text=True)
-# self._all_text = ''.join([tag for tag in tags])
-# self._prepare_text_to_speech(self._all_text)
-
- def _prepare_text_to_speech(self, page_text):
- i = 0
- j = 0
- word_begin = 0
- word_end = 0
- ignore_chars = [' ', '\n', u'\r', '_', '[', '{', ']', '}', '|',
- '<', '>', '*', '+', '/', '\\']
- ignore_set = set(ignore_chars)
- self.word_tuples = []
- len_page_text = len(page_text)
- while i < len_page_text:
- if page_text[i] not in ignore_set:
- word_begin = i
- j = i
- while j < len_page_text and page_text[j] not in ignore_set:
- j = j + 1
- word_end = j
- i = j
- word_tuple = (word_begin, word_end,
- page_text[word_begin: word_end])
- if word_tuple[2] != u'\r':
- self.word_tuples.append(word_tuple)
- i = i + 1
-
- def _scroll_page_end(self):
- v_upper = self._v_vscrollbar.props.adjustment.props.upper
- # v_page_size = self._v_vscrollbar.props.adjustment.props.page_size
- self._v_vscrollbar.set_value(v_upper)
-
- def _scroll_page(self):
- pageno = self._loaded_page
-
- v_upper = self._v_vscrollbar.props.adjustment.props.upper
- v_page_size = self._v_vscrollbar.props.adjustment.props.page_size
-
- scrollfactor = self._paginator.get_scrollfactor_pos_for_pageno(pageno)
- self._v_vscrollbar.set_value((v_upper - v_page_size) * scrollfactor)
-
- def _paginate(self):
- filelist = []
- for i in self._epub._navmap.get_flattoc():
- filelist.append(os.path.join(self._epub._tempdir, i))
- # init files info
- self._filelist = filelist
- self._paginator = _Paginator(filelist)
- self._paginator.connect('paginated', self._paginated_cb)
-
- def get_filelist(self):
- return self._filelist
-
- def get_tempdir(self):
- return self._epub._tempdir
-
- def _load_next_page(self):
- self._load_page(self._loaded_page + 1)
-
- def _load_prev_page(self):
- self._load_page(self._loaded_page - 1)
-
- def _v_scrollbar_value_changed_cb(self, scrollbar):
- if self._loaded_page < 1:
- return
- scrollval = scrollbar.get_value()
- scroll_upper = self._v_vscrollbar.props.adjustment.props.upper
- scroll_page_size = self._v_vscrollbar.props.adjustment.props.page_size
-
- if self.__going_fwd and not self._loaded_page == self._pagecount:
- if self._paginator.get_file_for_pageno(self._loaded_page) != \
- self._paginator.get_file_for_pageno(self._loaded_page + 1):
- # We don't need this if the next page is in another file
- return
-
- scrollfactor_next = \
- self._paginator.get_scrollfactor_pos_for_pageno(
- self._loaded_page + 1)
- if scrollval > 0:
- scrollfactor = scrollval / (scroll_upper - scroll_page_size)
- else:
- scrollfactor = 0
- if scrollfactor >= scrollfactor_next:
- self._on_page_changed(self._loaded_page, self._loaded_page + 1)
- elif self.__going_back and self._loaded_page > 1:
- if self._paginator.get_file_for_pageno(self._loaded_page) != \
- self._paginator.get_file_for_pageno(self._loaded_page - 1):
- return
-
- scrollfactor_cur = \
- self._paginator.get_scrollfactor_pos_for_pageno(
- self._loaded_page)
- if scrollval > 0:
- scrollfactor = scrollval / (scroll_upper - scroll_page_size)
- else:
- scrollfactor = 0
-
- if scrollfactor <= scrollfactor_cur:
- self._on_page_changed(self._loaded_page, self._loaded_page - 1)
-
- def _on_page_changed(self, oldpage, pageno):
- if oldpage == pageno:
- return
- self.__page_changed = True
- self._loaded_page = pageno
- self._scrollbar.handler_block(self._scrollbar_change_value_cb_id)
- self._scrollbar.set_value(pageno)
- self._scrollbar.handler_unblock(self._scrollbar_change_value_cb_id)
- # the indexes in read activity are zero based
- self.emit('page-changed', (oldpage - 1), (pageno - 1))
-
- def _load_page(self, pageno):
- if pageno > self._pagecount or pageno < 1:
- # TODO: Cause an exception
- return
- if self._loaded_page == pageno:
- return
-
- filename = self._paginator.get_file_for_pageno(pageno)
- filename = filename.replace('file://', '')
-
- if filename != self._loaded_filename:
- self._loaded_filename = filename
- if not self._file_loaded:
- # wait until the file is loaded
- return
- self._file_loaded = False
-
- """
- TODO: disabled because javascript can't be executed
- with the velocity needed
- # Copy javascript to highligth text to speech
- destpath, destname = os.path.split(filename.replace('file://', ''))
- shutil.copy('./epubview/highlight_words.js', destpath)
- self._insert_js_reference(filename.replace('file://', ''),
- destpath)
- IMPORTANT: Find a way to do this without modify the files
- now text highlight is implemented and the epub file is saved
- """
-
- if filename.endswith('xml'):
- dest = filename.replace('xml', 'xhtml')
- if not os.path.exists(dest):
- os.symlink(filename, dest)
- self._view.load_uri('file://' + dest)
- else:
- self._view.load_uri('file://' + filename)
- else:
- self._loaded_page = pageno
- self._scroll_page()
- self._on_page_changed(self._loaded_page, pageno)
-
- def _insert_js_reference(self, file_name, path):
- js_reference = ''
- o = open(file_name + '.tmp', 'a')
- for line in open(file_name):
- line = line.replace('', js_reference + '')
- o.write(line + "\n")
- o.close()
- shutil.copy(file_name + '.tmp', file_name)
-
- def _load_file(self, path):
- self._internal_link = None
- if path.find('#') > -1:
- self._internal_link = path[path.find('#'):]
- path = path[:path.find('#')]
-
- for filepath in self._filelist:
- if filepath.endswith(path):
- self._view.load_uri('file://' + filepath)
- oldpage = self._loaded_page
- self._loaded_page = \
- self._paginator.get_base_pageno_for_file(filepath)
- self._scroll_page()
- self._on_page_changed(oldpage, self._loaded_page)
- break
-
- def _scrollbar_change_value_cb(self, range, scrolltype, value):
- if scrolltype == Gtk.ScrollType.STEP_FORWARD:
- self.__going_fwd = True
- self.__going_back = False
- if not self._do_page_transition():
- self._view.move_cursor(Gtk.MovementStep.DISPLAY_LINES, 1)
- elif scrolltype == Gtk.ScrollType.STEP_BACKWARD:
- self.__going_fwd = False
- self.__going_back = True
- if not self._do_page_transition():
- self._view.move_cursor(Gtk.MovementStep.DISPLAY_LINES, -1)
- elif scrolltype == Gtk.ScrollType.JUMP or \
- scrolltype == Gtk.ScrollType.PAGE_FORWARD or \
- scrolltype == Gtk.ScrollType.PAGE_BACKWARD:
- if value > self._scrollbar.props.adjustment.props.upper:
- self._load_page(self._pagecount)
- else:
- self._load_page(round(value))
- else:
- print 'Warning: unknown scrolltype %s with value %f' \
- % (str(scrolltype), value)
-
- # FIXME: This should not be needed here
- self._scrollbar.set_value(self._loaded_page)
-
- if self.__page_changed:
- self.__page_changed = False
- return False
- else:
- return True
-
- def _paginated_cb(self, object):
- self._ready = True
-
- self._pagecount = self._paginator.get_total_pagecount()
- self._scrollbar.set_range(1.0, self._pagecount - 1.0)
- self._scrollbar.set_increments(1.0, 1.0)
- self._view.grab_focus()
- self._view.grab_default()
-
- def _destroy_cb(self, widget):
- self._epub.close()
diff --git a/epubview/highlight_words.js b/epubview/highlight_words.js
deleted file mode 100644
index ffa5e9a..0000000
--- a/epubview/highlight_words.js
+++ /dev/null
@@ -1,89 +0,0 @@
- var parentElement;
- var actualChild;
- var actualWord;
- var words;
- var originalNode = null;
- var modifiedNode = null;
-
- function trim(s) {
- s = ( s || '' ).replace( /^\s+|\s+$/g, '' );
- return s.replace(/[\n\r\t]/g,' ');
- }
-
-
- function init() {
- parentElement = document.getElementsByTagName("body")[0];
- actualChild = new Array();
- actualWord = 0;
- actualChild.push(0);
- }
-
- function highLightNextWordInt() {
- var nodeList = parentElement.childNodes;
- ini_posi = actualChild[actualChild.length - 1];
- for (var i=ini_posi; i < nodeList.length; i++) {
- var node = nodeList[i];
- if ((node.nodeName == "#text") && (trim(node.nodeValue) != '')) {
- node_text = trim(node.nodeValue);
- words = node_text.split(" ");
- if (actualWord < words.length) {
- originalNode = document.createTextNode(node.nodeValue);
-
- prev_text = '';
- for (var p1 = 0; p1 < actualWord; p1++) {
- prev_text = prev_text + words[p1] + " ";
- }
- var textNode1 = document.createTextNode(prev_text);
- var textNode2 = document.createTextNode(words[actualWord]+" ");
- post_text = '';
- for (var p2 = actualWord + 1; p2 < words.length; p2++) {
- post_text = post_text + words[p2] + " ";
- }
- var textNode3 = document.createTextNode(post_text);
- var newParagraph = document.createElement('p');
- var boldNode = document.createElement('b');
- boldNode.appendChild(textNode2);
- newParagraph.appendChild(textNode1);
- newParagraph.appendChild(boldNode);
- newParagraph.appendChild(textNode3);
-
- parentElement.insertBefore(newParagraph, node);
- parentElement.removeChild(node);
- modifiedNode = newParagraph;
-
- actualWord = actualWord + 1;
- if (actualWord >= words.length) {
- actualChild.pop();
- actualChild[actualChild.length - 1] = actualChild[actualChild.length - 1] + 2;
- actualWord = 0;
- parentElement = parentElement.parentNode;
- }
- }
- throw "exit";
- } else {
- if (node.childNodes.length > 0) {
- parentElement = node;
- actualChild.push(0);
- actualWord = 0;
- highLightNextWordInt();
- actualChild.pop();
- }
- }
- }
- return;
- }
-
-
- function highLightNextWord() {
- if (typeof parentElement == "undefined") {
- init();
- }
- if (originalNode != null) {
- modifiedNode.parentNode.insertBefore(originalNode, modifiedNode);
- modifiedNode.parentNode.removeChild(modifiedNode);
- }
- try {
- highLightNextWordInt();
- } catch(er) {
- }
- }
diff --git a/epubview/jobs.py b/epubview/jobs.py
deleted file mode 100644
index e8a5762..0000000
--- a/epubview/jobs.py
+++ /dev/null
@@ -1,327 +0,0 @@
-# Copyright 2009 One Laptop Per Child
-# Author: Sayamindu Dasgupta
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-from gi.repository import GObject
-from gi.repository import Gtk
-import widgets
-import math
-import os.path
-import xml.etree.ElementTree as etree
-
-import threading
-
-PAGE_WIDTH = 135
-PAGE_HEIGHT = 216
-
-
-def _pixel_to_mm(pixel, dpi):
- inches = pixel / dpi
- return int(inches / 0.03937)
-
-
-def _mm_to_pixel(mm, dpi):
- inches = mm * 0.03937
- return int(inches * dpi)
-
-
-class SearchThread(threading.Thread):
-
- def __init__(self, obj):
- threading.Thread.__init__(self)
- self.obj = obj
- self.stopthread = threading.Event()
-
- def _start_search(self):
- for entry in self.obj.flattoc:
- if self.stopthread.isSet():
- break
- filepath = os.path.join(self.obj._document.get_basedir(), entry)
- f = open(filepath)
- if self._searchfile(f):
- self.obj._matchfilelist.append(entry)
- f.close()
-
- self.obj._finished = True
- GObject.idle_add(self.obj.emit, 'updated')
-
- return False
-
- def _searchfile(self, fileobj):
- tree = etree.parse(fileobj)
- root = tree.getroot()
-
- body = None
- for child in root:
- if child.tag.endswith('body'):
- body = child
-
- if body is None:
- return False
-
- for child in body.iter():
- if child.text is not None:
- if child.text.lower().find(self.obj._text.lower()) > -1:
- return True
-
- return False
-
- def run(self):
- self._start_search()
-
- def stop(self):
- self.stopthread.set()
-
-
-class _JobPaginator(GObject.GObject):
-
- __gsignals__ = {
- 'paginated': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([])),
- }
-
- def __init__(self, filelist):
- GObject.GObject.__init__(self)
-
- self._filelist = filelist
- self._filedict = {}
- self._pagemap = {}
-
- self._bookheight = 0
- self._count = 0
- self._pagecount = 0
-
- # TODO
- """
- self._screen = Gdk.Screen.get_default()
- self._old_fontoptions = self._screen.get_font_options()
- options = cairo.FontOptions()
- options.set_hint_style(cairo.HINT_STYLE_MEDIUM)
- options.set_antialias(cairo.ANTIALIAS_GRAY)
- options.set_subpixel_order(cairo.SUBPIXEL_ORDER_DEFAULT)
- options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
- self._screen.set_font_options(options)
- """
-
- self._temp_win = Gtk.Window()
- self._temp_view = widgets._WebView(only_to_measure=True)
-
- settings = self._temp_view.get_settings()
- settings.props.default_font_family = 'DejaVu LGC Serif'
- settings.props.sans_serif_font_family = 'DejaVu LGC Sans'
- settings.props.serif_font_family = 'DejaVu LGC Serif'
- settings.props.monospace_font_family = 'DejaVu LGC Sans Mono'
- settings.props.enforce_96_dpi = True
- # FIXME: This does not seem to work
- # settings.props.auto_shrink_images = False
- settings.props.enable_plugins = False
- settings.props.default_font_size = 12
- settings.props.default_monospace_font_size = 10
- settings.props.default_encoding = 'utf-8'
-
- sw = Gtk.ScrolledWindow()
- sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER)
- self._dpi = 96
- self._single_page_height = _mm_to_pixel(PAGE_HEIGHT, self._dpi)
- sw.set_size_request(_mm_to_pixel(PAGE_WIDTH, self._dpi),
- self._single_page_height)
- sw.add(self._temp_view)
- self._temp_win.add(sw)
- self._temp_view.connect('load-finished', self._page_load_finished_cb)
-
- self._temp_win.show_all()
- self._temp_win.unmap()
-
- self._temp_view.open(self._filelist[self._count])
-
- def get_single_page_height(self):
- """
- Returns the height in pixels of a single page
- """
- return self._single_page_height
-
- def get_next_filename(self, actual_filename):
- for n in range(len(self._filelist)):
- filename = self._filelist[n]
- if filename == actual_filename:
- if n < len(self._filelist):
- return self._filelist[n + 1]
- return None
-
- def _page_load_finished_cb(self, v, frame):
- f = v.get_main_frame()
- pageheight = v.get_page_height()
-
- if pageheight <= self._single_page_height:
- pages = 1
- else:
- pages = pageheight / float(self._single_page_height)
- for i in range(1, int(math.ceil(pages) + 1)):
- if pages - i < 0:
- pagelen = (pages - math.floor(pages)) / pages
- else:
- pagelen = 1 / pages
- self._pagemap[float(self._pagecount + i)] = \
- (f.props.uri, (i - 1) / math.ceil(pages), pagelen)
-
- self._pagecount += int(math.ceil(pages))
- self._filedict[f.props.uri.replace('file://', '')] = \
- (math.ceil(pages), math.ceil(pages) - pages)
- self._bookheight += pageheight
-
- if self._count + 1 >= len(self._filelist):
- # TODO
- # self._screen.set_font_options(self._old_fontoptions)
- self.emit('paginated')
- GObject.idle_add(self._cleanup)
- else:
- self._count += 1
- self._temp_view.open(self._filelist[self._count])
-
- def _cleanup(self):
- self._temp_win.destroy()
-
- def get_file_for_pageno(self, pageno):
- '''
- Returns the file in which pageno occurs
- '''
- return self._pagemap[pageno][0]
-
- def get_scrollfactor_pos_for_pageno(self, pageno):
- '''
- Returns the position scrollfactor (fraction) for pageno
- '''
- return self._pagemap[pageno][1]
-
- def get_scrollfactor_len_for_pageno(self, pageno):
- '''
- Returns the length scrollfactor (fraction) for pageno
- '''
- return self._pagemap[pageno][2]
-
- def get_pagecount_for_file(self, filename):
- '''
- Returns the number of pages in file
- '''
- return self._filedict[filename][0]
-
- def get_base_pageno_for_file(self, filename):
- '''
- Returns the pageno which begins in filename
- '''
- for key in self._pagemap.keys():
- if self._pagemap[key][0].replace('file://', '') == filename:
- return key
-
- return None
-
- def get_remfactor_for_file(self, filename):
- '''
- Returns the remainder
- factor (1 - fraction length of last page in file)
- '''
- return self._filedict[filename][1]
-
- def get_total_pagecount(self):
- '''
- Returns the total pagecount for the Epub file
- '''
- return self._pagecount
-
- def get_total_height(self):
- '''
- Returns the total height of the Epub in pixels
- '''
- return self._bookheight
-
-
-class _JobFind(GObject.GObject):
- __gsignals__ = {
- 'updated': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([])),
- }
-
- def __init__(self, document, start_page, n_pages, text,
- case_sensitive=False):
- """
- Only case_sensitive=False is implemented
- """
- GObject.GObject.__init__(self)
-
- self._finished = False
- self._document = document
- self._start_page = start_page
- self._n_pages = n_pages
- self._text = text
- self._case_sensitive = case_sensitive
- self.flattoc = self._document.get_flattoc()
- self._matchfilelist = []
- self._current_file_index = 0
- self.threads = []
-
- s_thread = SearchThread(self)
- self.threads.append(s_thread)
- s_thread.start()
-
- def cancel(self):
- '''
- Cancels the search job
- '''
- for s_thread in self.threads:
- s_thread.stop()
-
- def is_finished(self):
- '''
- Returns True if the entire search job has been finished
- '''
- return self._finished
-
- def get_next_file(self):
- '''
- Returns the next file which has the search pattern
- '''
- self._current_file_index += 1
- try:
- path = self._matchfilelist[self._current_file_index]
- except IndexError:
- self._current_file_index = 0
- path = self._matchfilelist[self._current_file_index]
-
- return path
-
- def get_prev_file(self):
- '''
- Returns the previous file which has the search pattern
- '''
- self._current_file_index -= 1
- try:
- path = self._matchfilelist[self._current_file_index]
- except IndexError:
- self._current_file_index = -1
- path = self._matchfilelist[self._current_file_index]
-
- return path
-
- def get_search_text(self):
- '''
- Returns the search text
- '''
- return self._text
-
- def get_case_sensitive(self):
- '''
- Returns True if the search is case-sensitive
- '''
- return self._case_sensitive
diff --git a/epubview/navmap.py b/epubview/navmap.py
deleted file mode 100644
index bbb1f44..0000000
--- a/epubview/navmap.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import xml.etree.ElementTree as etree
-from gi.repository import Gtk
-
-
-class NavPoint(object):
-
- def __init__(self, label, contentsrc, children=[]):
- self._label = label
- self._contentsrc = contentsrc
- self._children = children
-
- def get_label(self):
- return self._label
-
- def get_contentsrc(self):
- return self._contentsrc
-
- def get_children(self):
- return self._children
-
-
-class NavMap(object):
- def __init__(self, opffile, ncxfile, basepath):
- self._basepath = basepath
- self._opffile = opffile
- self._tree = etree.parse(ncxfile)
- self._root = self._tree.getroot()
- self._gtktreestore = Gtk.TreeStore(str, str)
- self._flattoc = []
-
- self._populate_flattoc()
- self._populate_toc()
-
- def _populate_flattoc(self):
- tree = etree.parse(self._opffile)
- root = tree.getroot()
-
- itemmap = {}
- manifest = root.find('.//{http://www.idpf.org/2007/opf}manifest')
- for element in manifest.iterfind('{http://www.idpf.org/2007/opf}item'):
- itemmap[element.get('id')] = element
-
- spine = root.find('.//{http://www.idpf.org/2007/opf}spine')
- for element in spine.iterfind('{http://www.idpf.org/2007/opf}itemref'):
- idref = element.get('idref')
- href = itemmap[idref].get('href')
- self._flattoc.append(self._basepath + href)
-
- self._opffile.close()
-
- def _populate_toc(self):
- navmap = self._root.find(
- '{http://www.daisy.org/z3986/2005/ncx/}navMap')
- for navpoint in navmap.iterfind(
- './{http://www.daisy.org/z3986/2005/ncx/}navPoint'):
- self._process_navpoint(navpoint)
-
- def _gettitle(self, navpoint):
- text = navpoint.find(
- './{http://www.daisy.org/z3986/2005/ncx/}' +
- 'navLabel/{http://www.daisy.org/z3986/2005/ncx/}text')
- return text.text
-
- def _getcontent(self, navpoint):
- text = navpoint.find(
- './{http://www.daisy.org/z3986/2005/ncx/}content')
- if text is not None:
- return self._basepath + text.get('src')
- else:
- return ""
-
- def _process_navpoint(self, navpoint, parent=None):
- title = self._gettitle(navpoint)
- content = self._getcontent(navpoint)
-
- # print title, content
-
- iter = self._gtktreestore.append(parent, [title, content])
- # self._flattoc.append((title, content))
-
- childnavpointlist = list(navpoint.iterfind(
- './{http://www.daisy.org/z3986/2005/ncx/}navPoint'))
-
- if len(childnavpointlist):
- for childnavpoint in childnavpointlist:
- self._process_navpoint(childnavpoint, parent=iter)
- else:
- return
-
- def get_gtktreestore(self):
- '''
- Returns a GtkTreeModel representation of the
- Epub table of contents
- '''
- return self._gtktreestore
-
- def get_flattoc(self):
- '''
- Returns a flat (linear) list of files to be
- rendered.
- '''
- return self._flattoc
diff --git a/epubview/widgets.py b/epubview/widgets.py
deleted file mode 100644
index ff9de7c..0000000
--- a/epubview/widgets.py
+++ /dev/null
@@ -1,117 +0,0 @@
-import logging
-
-import gi
-gi.require_version('WebKit', '3.0')
-
-from gi.repository import WebKit
-from gi.repository import Gdk
-from gi.repository import GObject
-
-
-class _WebView(WebKit.WebView):
-
- __gsignals__ = {
- 'touch-change-page': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE,
- ([bool])), }
-
- def __init__(self, only_to_measure=False):
- WebKit.WebView.__init__(self)
- self._only_to_measure = only_to_measure
-
- def setup_touch(self):
- self.get_window().set_events(
- self.get_window().get_events() | Gdk.EventMask.TOUCH_MASK)
- self.connect('event', self.__event_cb)
-
- def __event_cb(self, widget, event):
- if event.type == Gdk.EventType.TOUCH_BEGIN:
- x = event.touch.x
- view_width = widget.get_allocation().width
- if x > view_width * 3 / 4:
- self.emit('touch-change-page', True)
- elif x < view_width * 1 / 4:
- self.emit('touch-change-page', False)
-
- def get_page_height(self):
- '''
- Gets height (in pixels) of loaded (X)HTML page.
- This is done via javascript at the moment
- '''
- hide_scrollbar_js = ''
- if self._only_to_measure:
- hide_scrollbar_js = \
- 'document.documentElement.style.overflow = "hidden";'
-
- oldtitle = self.get_main_frame().get_title()
-
- js = """
- document.documentElement.style.margin = "50px";
- if (document.body == null) {
- document.title = 0;
- } else {
- %s
- document.title=Math.max(document.body.scrollHeight,
- document.body.offsetHeight,
- document.documentElement.clientHeight,
- document.documentElement.scrollHeight,
- document.documentElement.offsetHeight);
- };
- """ % hide_scrollbar_js
- self.execute_script(js)
- ret = self.get_main_frame().get_title()
- self.execute_script('document.title=%s;' % oldtitle)
- try:
- return int(ret)
- except ValueError:
- return 0
-
- def add_bottom_padding(self, incr):
- '''
- Adds incr pixels of padding to the end of the loaded (X)HTML page.
- This is done via javascript at the moment
- '''
- js = """
- var newdiv = document.createElement("div");
- newdiv.style.height = "%dpx";
- document.body.appendChild(newdiv);
- """ % incr
- self.execute_script(js)
-
- def highlight_next_word(self):
- '''
- Highlight next word (for text to speech)
- '''
- self.execute_script('highLightNextWord();')
-
- def go_to_link(self, id_link):
- self.execute_script('window.location.href = "%s";' % id_link)
-
- def get_vertical_position_element(self, id_link):
- '''
- Get the vertical position of a element, in pixels
- '''
- # remove the first '#' char
- id_link = id_link[1:]
- oldtitle = self.get_main_frame().get_title()
- js = """
- obj = document.getElementById('%s');
- var top = 0;
- if(obj.offsetParent) {
- while(1) {
- top += obj.offsetTop;
- if(!obj.offsetParent) {
- break;
- };
- obj = obj.offsetParent;
- };
- } else if(obj.y) {
- top += obj.y;
- };
- document.title=top;""" % id_link
- self.execute_script(js)
- ret = self.get_main_frame().get_title()
- self.execute_script('document.title=%s;' % oldtitle)
- try:
- return int(ret)
- except ValueError:
- return 0
diff --git a/readactivity.py b/readactivity.py
index 2d78f83..6143876 100644
--- a/readactivity.py
+++ b/readactivity.py
@@ -822,7 +822,7 @@
del self.unused_download_tubes
# Use the suggested file, the mime is not recognized if the extension
- # is wrong in some cases (epub)
+ # is wrong in some cases
temp_dir = os.path.dirname(tempfile)
new_name = os.path.join(temp_dir, suggested_name)
os.rename(tempfile, new_name)
@@ -976,10 +976,7 @@
else:
mimetype = self.metadata['mime_type']
- if mimetype == 'application/epub+zip':
- import epubadapter
- self._view = epubadapter.EpubViewer()
- elif mimetype == 'text/plain' or mimetype == 'application/zip':
+ if mimetype == 'text/plain' or mimetype == 'application/zip':
import textadapter
self._view = textadapter.TextViewer()
elif mimetype == 'application/x-cbz':