diff options
author | Sayamindu Dasgupta <sayamindu@gmail.com> | 2009-09-02 18:36:54 (GMT) |
---|---|---|
committer | Sayamindu Dasgupta <sayamindu@gmail.com> | 2009-09-02 18:36:54 (GMT) |
commit | 47fe7dd173869aca32e6ea59286358da525f9336 (patch) | |
tree | 8acd930b53fe18d8ca7764da55cad83b8d2fc26a | |
parent | 0433b67dc2d74c16d6bcbe083beefbcd7134d686 (diff) |
Sync with pyepubview, revision 25
-rw-r--r-- | epubview/epub.py | 70 | ||||
-rw-r--r-- | epubview/epubinfo.py | 4 | ||||
-rw-r--r-- | epubview/epubview.py | 60 | ||||
-rw-r--r-- | epubview/jobs.py | 42 | ||||
-rw-r--r-- | epubview/navmap.py | 39 | ||||
-rw-r--r-- | epubview/widgets.py | 18 |
6 files changed, 182 insertions, 51 deletions
diff --git a/epubview/epub.py b/epubview/epub.py index f49b0d7..71267aa 100644 --- a/epubview/epub.py +++ b/epubview/epub.py @@ -28,26 +28,23 @@ class _Epub(object): def __init__(self, filepath): self._filepath = filepath self._zobject = None - self._obffile = None - self._titlepage = None - self._obfpath = None + self._opfpath = None self._ncxpath = None - self._ncxfile = 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_obf() + self._get_opf() self._get_ncx() - self._get_titlepage() - self._ncxfile = self._zobject.open(self._ncxpath) - self._navmap = navmap.NavMap(self._ncxfile, self._basepath, self._titlepage) + ncxfile = self._zobject.open(self._ncxpath) + opffile = self._zobject.open(self._opfpath) + self._navmap = navmap.NavMap(opffile, ncxfile, self._basepath) - self._obffile = self._zobject.open(self._obfpath) - self._info = epubinfo.EpubInfo(self._obffile) + opffile = self._zobject.open(self._opfpath) + self._info = epubinfo.EpubInfo(opffile) self._unzip() @@ -65,7 +62,7 @@ class _Epub(object): os.chdir(orig_cwd) - def _get_obf(self): + def _get_opf(self): containerfile = self._zobject.open('META-INF/container.xml') tree = etree.parse(containerfile) @@ -73,10 +70,10 @@ class _Epub(object): for element in root.iterfind('.//{urn:oasis:names:tc:opendocument:xmlns:container}rootfile'): if element.get('media-type') == 'application/oebps-package+xml': - self._obfpath = element.get('full-path') + self._opfpath = element.get('full-path') - if self._obfpath.rpartition('/')[0]: - self._basepath = self._obfpath.rpartition('/')[0] + '/' + if self._opfpath.rpartition('/')[0]: + self._basepath = self._opfpath.rpartition('/')[0] + '/' else: self._basepath = '' @@ -84,30 +81,20 @@ class _Epub(object): def _get_ncx(self): - obffile = self._zobject.open(self._obfpath) + opffile = self._zobject.open(self._opfpath) - tree = etree.parse(obffile) + 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('media-type') == 'application/x-dtbncx+xml' or \ - element.get('id') == 'ncx': + if element.get('id') == tocid: self._ncxpath = self._basepath + element.get('href') - obffile.close() - - def _get_titlepage(self): - obffile = self._zobject.open(self._obfpath) - tree = etree.parse(obffile) - root = tree.getroot() + opffile.close() - for element in root.iterfind('.//{http://www.idpf.org/2007/opf}item'): - if element.get('id') == 'titlepage': - self._titlepage = self._basepath + element.get('href') - - obffile.close() - - def _verify(self): ''' Method to crudely check to verify that what we @@ -124,23 +111,42 @@ class _Epub(object): mtypefile = self._zobject.open('mimetype') mimetype = mtypefile.readline() - if mimetype != 'application/epub+zip': + if not mimetype.startswith('application/epub+zip'): # Some files seem to have trailing characters 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 for the open Epub file + ''' return self._info 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 index ddf9ad5..d25dfc2 100644 --- a/epubview/epubinfo.py +++ b/epubview/epubinfo.py @@ -3,8 +3,8 @@ from lxml import etree class EpubInfo(): #TODO: Cover the entire DC range - def __init__(self, file): - self._tree = etree.parse(file) + 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') diff --git a/epubview/epubview.py b/epubview/epubview.py index 5c2c7a2..7300bd0 100644 --- a/epubview/epubview.py +++ b/epubview/epubview.py @@ -98,6 +98,9 @@ class _View(gtk.HBox): self._view.set_flags(gtk.CAN_DEFAULT|gtk.CAN_FOCUS) def set_document(self, epubdocumentinstance): + ''' + Sets document (should be a Epub instance) + ''' self._epub = epubdocumentinstance gobject.idle_add(self._paginate) @@ -116,15 +119,27 @@ class _View(gtk.HBox): raise AttributeError, 'unknown property %s' % property.name def get_has_selection(self): + ''' + Returns True if any part of the content is selected + ''' return self.get_property('has-selection') def get_zoom(self): + ''' + Returns the current zoom level + ''' return self.get_property('zoom') def set_zoom(self, value): + ''' + Sets the current zoom level + ''' self.set_property('zoom', value) def zoom_in(self): + ''' + Zooms in (increases zoom level by 0.1) + ''' if self.can_zoom_in(): self.set_zoom(self.get_zoom() + 0.1) return True @@ -132,6 +147,9 @@ class _View(gtk.HBox): return False def zoom_out(self): + ''' + Zooms out (decreases zoom level by 0.1) + ''' if self.can_zoom_out(): self.set_zoom(self.get_zoom() - 0.1) return True @@ -139,21 +157,33 @@ class _View(gtk.HBox): return False def can_zoom_in(self): + ''' + Returns True if it is possible to zoom in further + ''' if self.zoom < 4: return True else: return False def can_zoom_out(self): + ''' + Returns True if it is possible to zoom out further + ''' if self.zoom > 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) @@ -161,27 +191,46 @@ class _View(gtk.HBox): 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.SCROLL_PAGE_BACKWARD and gtk.SCROLL_PAGE_FORWARD + ''' if scrolltype == gtk.SCROLL_PAGE_BACKWARD: self.__going_back = True self.__going_fwd = False @@ -196,9 +245,15 @@ class _View(gtk.HBox): print ('Got unsupported scrolltype %s' % str(scrolltype)) 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() self._view.grab_default() @@ -212,6 +267,9 @@ class _View(gtk.HBox): self._load_file(path) def find_previous(self): + ''' + Highlights the previous matching item for current search + ''' self._view.grab_focus() self._view.grab_default() @@ -335,7 +393,7 @@ class _View(gtk.HBox): def _paginate(self): filelist = [] for i in self._epub._navmap.get_flattoc(): - filelist.append(os.path.join(self._epub._tempdir, i[1])) + filelist.append(os.path.join(self._epub._tempdir, i)) self._paginator = _Paginator(filelist) self._paginator.connect('paginated', self._paginated_cb) diff --git a/epubview/jobs.py b/epubview/jobs.py index de276b3..4637e2f 100644 --- a/epubview/jobs.py +++ b/epubview/jobs.py @@ -52,8 +52,7 @@ class SearchThread(threading.Thread): for entry in self.obj.flattoc: if self.stopthread.isSet(): break - name, file = entry - filepath = os.path.join(self.obj._document.get_basedir(), file) + filepath = os.path.join(self.obj._document.get_basedir(), entry) f = open(filepath) if self._searchfile(f): self.obj._matchfilelist.append(file) @@ -168,24 +167,45 @@ class _JobPaginator(gobject.GObject): 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, file): + ''' + Returns the number of pages in file + ''' return self._filedict[file][0] def get_remfactor_for_file(self, file): + ''' + Returns the remainder factor (1 - fraction length of last page in file) + ''' return self._filedict[file][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 @@ -215,13 +235,22 @@ class _JobFind(gobject.GObject): 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] @@ -232,6 +261,9 @@ class _JobFind(gobject.GObject): 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] @@ -242,7 +274,13 @@ class _JobFind(gobject.GObject): 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 index cdeb265..a0a1799 100644 --- a/epubview/navmap.py +++ b/epubview/navmap.py @@ -18,19 +18,34 @@ class NavPoint(object): class NavMap(object): - def __init__(self, opffile, basepath, titlepage): + def __init__(self, opffile, ncxfile, basepath): self._basepath = basepath - self._tree = etree.parse(opffile) + 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() - if titlepage and self._flattoc[0][1] != titlepage: - self._flattoc.insert(0, ('Title Page', titlepage)) - self._gtktreestore.insert(None, 0, ['Title Page', titlepage]) - 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'): @@ -48,8 +63,10 @@ class NavMap(object): title = self._gettitle(navpoint) content = self._getcontent(navpoint) + #print title, content + iter = self._gtktreestore.append(parent, [title, content]) - self._flattoc.append((title, content)) + #self._flattoc.append((title, content)) childnavpointlist = list(navpoint.iterfind('./{http://www.daisy.org/z3986/2005/ncx/}navPoint')) @@ -60,9 +77,17 @@ class NavMap(object): 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 #t = TocParser('/home/sayamindu/Desktop/Test/OPS/fb.ncx')
\ No newline at end of file diff --git a/epubview/widgets.py b/epubview/widgets.py index c52d590..5b6dd68 100644 --- a/epubview/widgets.py +++ b/epubview/widgets.py @@ -1,27 +1,31 @@ +import webkit import gtk -try: - import webkit -except ImportError: - import os, sys - sys.path.append(os.path.join(os.environ['SUGAR_BUNDLE_PATH'], 'epubview', 'modules')) - import webkit - class _WebView(webkit.WebView): def __init__(self): webkit.WebView.__init__(self) def get_page_height(self): + ''' + Gets height (in pixels) of loaded (X)HTML page. + This is done via javascript at the moment + ''' #TODO: Need to check status of page load js = 'oldtitle=document.title;document.title=document.body.clientHeight;' self.execute_script(js) ret = self.get_main_frame().get_title() js = 'document.title=oldtitle;' self.execute_script(js) + if ret is None: + return 0 return int(ret) 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) |