E-book viewer: More accurate sorting of bookmarks by position in book

This commit is contained in:
Kovid Goyal 2014-08-10 08:28:09 +05:30
parent caad45e8d8
commit a0c4206477
3 changed files with 42 additions and 2 deletions

View File

@ -167,3 +167,32 @@ def parser():
_parser = Parser()
return _parser
def get_steps(pcfi):
ans = tuple(pcfi['steps'])
if 'redirect' in pcfi:
ans += get_steps(pcfi['redirect'])
return ans
def cfi_sort_key(cfi, only_path=True):
p = parser()
try:
if only_path:
pcfi = p.parse_path(cfi)[0]
else:
parent, start = p.parse_epubcfi(cfi)[:2]
pcfi = start or parent
except Exception:
import traceback
traceback.print_exc()
return ()
if not pcfi:
import sys
print ('Failed to parse CFI: %r' % pcfi, file=sys.stderr)
return ()
steps = get_steps(pcfi)
step_nums = tuple(s.get('num', 0) for s in steps)
step = steps[-1] if steps else {}
offsets = (step.get('temporal_offset', 0), tuple(reversed(step.get('spatial_offset', (0, 0)))), step.get('text_offset', 0), )
return (step_nums, offsets)

View File

@ -9,10 +9,20 @@ __copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import unittest
from future_builtins import map
from calibre.ebooks.epub.cfi.parse import parser
from calibre.ebooks.epub.cfi.parse import parser, cfi_sort_key
class Tests(unittest.TestCase):
def test_sorting(self):
null_offsets = (0, (0, 0), 0)
for path, key in [
('/1/2/3', ((1, 2, 3), null_offsets)),
('/1[id]:34[yyyy]', ((1,), (0, (0, 0), 34))),
('/1@1:2', ((1,), (0, (2, 1), 0))),
('/1~1.2', ((1,), (1.2, (0, 0), 0))),
]:
self.assertEqual(cfi_sort_key(path), key)
def test_parsing(self):
p = parser()
def step(x):

View File

@ -173,9 +173,10 @@ class BookmarkManager(QWidget):
self.edited.emit(bm)
def sort_by_pos(self):
from calibre.ebooks.epub.cfi.parse import cfi_sort_key
def pos_key(b):
if b.get('type', None) == 'cfi':
return b['spine'], b['pos']
return b['spine'], cfi_sort_key(b['pos'])
return (None, None)
bm = self.get_bookmarks()
bm.sort(key=pos_key)