mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Pull from trunk
This commit is contained in:
commit
a4fe814d52
@ -166,6 +166,17 @@ class HTMLPreProcessor(object):
|
|||||||
(re.compile(u'`\s*(<br.*?>)*\s*O', re.UNICODE), lambda match: u'Ò'),
|
(re.compile(u'`\s*(<br.*?>)*\s*O', re.UNICODE), lambda match: u'Ò'),
|
||||||
(re.compile(u'`\s*(<br.*?>)*\s*u', re.UNICODE), lambda match: u'ù'),
|
(re.compile(u'`\s*(<br.*?>)*\s*u', re.UNICODE), lambda match: u'ù'),
|
||||||
(re.compile(u'`\s*(<br.*?>)*\s*U', re.UNICODE), lambda match: u'Ù'),
|
(re.compile(u'`\s*(<br.*?>)*\s*U', re.UNICODE), lambda match: u'Ù'),
|
||||||
|
# ` with letter before
|
||||||
|
(re.compile(u'a\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'à'),
|
||||||
|
(re.compile(u'A\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'À'),
|
||||||
|
(re.compile(u'e\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'è'),
|
||||||
|
(re.compile(u'E\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'È'),
|
||||||
|
(re.compile(u'i\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'ì'),
|
||||||
|
(re.compile(u'I\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'Ì'),
|
||||||
|
(re.compile(u'o\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'ò'),
|
||||||
|
(re.compile(u'O\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'Ò'),
|
||||||
|
(re.compile(u'u\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'ù'),
|
||||||
|
(re.compile(u'U\s*(<br.*?>)*\s*`', re.UNICODE), lambda match: u'Ù'),
|
||||||
|
|
||||||
# ´
|
# ´
|
||||||
(re.compile(u'´\s*(<br.*?>)*\s*a', re.UNICODE), lambda match: u'á'),
|
(re.compile(u'´\s*(<br.*?>)*\s*a', re.UNICODE), lambda match: u'á'),
|
||||||
|
@ -207,6 +207,7 @@ class PML_HTMLizer(object):
|
|||||||
while html != old:
|
while html != old:
|
||||||
old = html
|
old = html
|
||||||
html = self.cleanup_html_remove_redundant(html)
|
html = self.cleanup_html_remove_redundant(html)
|
||||||
|
html = re.sub(r'(?imu)^\s*', '', html)
|
||||||
return html
|
return html
|
||||||
|
|
||||||
def cleanup_html_remove_redundant(self, html):
|
def cleanup_html_remove_redundant(self, html):
|
||||||
@ -216,7 +217,7 @@ class PML_HTMLizer(object):
|
|||||||
html = re.sub(r'(?u)%s\s*%s' % (open % '.*?', close), '', html)
|
html = re.sub(r'(?u)%s\s*%s' % (open % '.*?', close), '', html)
|
||||||
else:
|
else:
|
||||||
html = re.sub(r'(?u)%s\s*%s' % (open, close), '', html)
|
html = re.sub(r'(?u)%s\s*%s' % (open, close), '', html)
|
||||||
html = re.sub(r'<p>\s*</p>', '', html)
|
html = re.sub(r'(?imu)<p>\s*</p>', '', html)
|
||||||
return html
|
return html
|
||||||
|
|
||||||
def start_line(self):
|
def start_line(self):
|
||||||
@ -556,7 +557,7 @@ class PML_HTMLizer(object):
|
|||||||
text = t
|
text = t
|
||||||
else:
|
else:
|
||||||
self.toc.add_item(os.path.basename(self.file_name), id, value)
|
self.toc.add_item(os.path.basename(self.file_name), id, value)
|
||||||
text = '<span id="%s"></span>%s' % (id, t)
|
text = '%s<span id="%s"></span>' % (t, id)
|
||||||
elif c == 'm':
|
elif c == 'm':
|
||||||
empty = False
|
empty = False
|
||||||
src = self.code_value(line)
|
src = self.code_value(line)
|
||||||
|
@ -77,7 +77,7 @@ def separate_paragraphs_print_formatted(txt):
|
|||||||
|
|
||||||
def preserve_spaces(txt):
|
def preserve_spaces(txt):
|
||||||
txt = txt.replace(' ', ' ')
|
txt = txt.replace(' ', ' ')
|
||||||
txt = txt.replace('\t', '	')
|
txt = txt.replace('\t', ' ')
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def opf_writer(path, opf_name, manifest, spine, mi):
|
def opf_writer(path, opf_name, manifest, spine, mi):
|
||||||
|
@ -121,10 +121,8 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
def set_device_connected(self, is_connected):
|
def set_device_connected(self, is_connected):
|
||||||
self.device_connected = is_connected
|
self.device_connected = is_connected
|
||||||
self.db.refresh_ondevice()
|
self.db.refresh_ondevice()
|
||||||
self.refresh()
|
self.refresh() # does a resort()
|
||||||
self.research()
|
self.research()
|
||||||
if is_connected and self.sorted_on[0] == 'ondevice':
|
|
||||||
self.resort()
|
|
||||||
|
|
||||||
def set_book_on_device_func(self, func):
|
def set_book_on_device_func(self, func):
|
||||||
self.book_on_device = func
|
self.book_on_device = func
|
||||||
@ -249,7 +247,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
# the search and count records for restrictions
|
# the search and count records for restrictions
|
||||||
self.searched.emit(True)
|
self.searched.emit(True)
|
||||||
|
|
||||||
def sort(self, col, order, reset=True):
|
def sort(self, col, order, reset=True, update_history=True):
|
||||||
if not self.db:
|
if not self.db:
|
||||||
return
|
return
|
||||||
self.about_to_be_sorted.emit(self.db.id)
|
self.about_to_be_sorted.emit(self.db.id)
|
||||||
@ -260,23 +258,23 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
self.clear_caches()
|
self.clear_caches()
|
||||||
self.reset()
|
self.reset()
|
||||||
self.sorted_on = (label, order)
|
self.sorted_on = (label, order)
|
||||||
|
if update_history:
|
||||||
self.sort_history.insert(0, self.sorted_on)
|
self.sort_history.insert(0, self.sorted_on)
|
||||||
self.sorting_done.emit(self.db.index)
|
self.sorting_done.emit(self.db.index)
|
||||||
|
|
||||||
def refresh(self, reset=True):
|
def refresh(self, reset=True):
|
||||||
try:
|
|
||||||
col = self.column_map.index(self.sorted_on[0])
|
|
||||||
except:
|
|
||||||
col = 0
|
|
||||||
self.db.refresh(field=None)
|
self.db.refresh(field=None)
|
||||||
self.sort(col, self.sorted_on[1], reset=reset)
|
self.resort(reset=reset)
|
||||||
|
|
||||||
def resort(self, reset=True):
|
def resort(self, reset=True, history=5): # Bug report needed history=4 :)
|
||||||
|
for col,ord in reversed(self.sort_history[:history]):
|
||||||
try:
|
try:
|
||||||
col = self.column_map.index(self.sorted_on[0])
|
col = self.column_map.index(col)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
col = 0
|
col = 0
|
||||||
self.sort(col, self.sorted_on[1], reset=reset)
|
self.sort(col, ord, reset=False, update_history=False)
|
||||||
|
if reset:
|
||||||
|
self.reset()
|
||||||
|
|
||||||
def research(self, reset=True):
|
def research(self, reset=True):
|
||||||
self.search(self.last_search, reset=reset)
|
self.search(self.last_search, reset=reset)
|
||||||
|
@ -512,7 +512,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
_('The saved search name %s is already used.')%val).exec_()
|
_('The saved search name %s is already used.')%val).exec_()
|
||||||
return False
|
return False
|
||||||
saved_searches().rename(unicode(item.data(role).toString()), val)
|
saved_searches().rename(unicode(item.data(role).toString()), val)
|
||||||
self.tags_view.search_item_renamed.emit()
|
item.tag.name = val
|
||||||
|
self.tags_view.search_item_renamed.emit() # Does a refresh
|
||||||
else:
|
else:
|
||||||
if key == 'series':
|
if key == 'series':
|
||||||
self.db.rename_series(item.tag.id, val)
|
self.db.rename_series(item.tag.id, val)
|
||||||
@ -669,7 +670,7 @@ class TagBrowserMixin(object): # {{{
|
|||||||
self.tags_view.saved_search_edit.connect(self.do_saved_search_edit)
|
self.tags_view.saved_search_edit.connect(self.do_saved_search_edit)
|
||||||
self.tags_view.author_sort_edit.connect(self.do_author_sort_edit)
|
self.tags_view.author_sort_edit.connect(self.do_author_sort_edit)
|
||||||
self.tags_view.tag_item_renamed.connect(self.do_tag_item_renamed)
|
self.tags_view.tag_item_renamed.connect(self.do_tag_item_renamed)
|
||||||
self.tags_view.search_item_renamed.connect(self.saved_search.clear_to_help)
|
self.tags_view.search_item_renamed.connect(self.saved_searches_changed)
|
||||||
self.edit_categories.clicked.connect(lambda x:
|
self.edit_categories.clicked.connect(lambda x:
|
||||||
self.do_user_categories_edit())
|
self.do_user_categories_edit())
|
||||||
|
|
||||||
|
@ -141,6 +141,8 @@ class ResultCache(SearchQueryParser):
|
|||||||
for x in self.iterall():
|
for x in self.iterall():
|
||||||
yield x[idx]
|
yield x[idx]
|
||||||
|
|
||||||
|
# Search functions {{{
|
||||||
|
|
||||||
def universal_set(self):
|
def universal_set(self):
|
||||||
return set([i[0] for i in self._data if i is not None])
|
return set([i[0] for i in self._data if i is not None])
|
||||||
|
|
||||||
@ -462,6 +464,30 @@ class ResultCache(SearchQueryParser):
|
|||||||
continue
|
continue
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
def search(self, query, return_matches=False):
|
||||||
|
ans = self.search_getting_ids(query, self.search_restriction)
|
||||||
|
if return_matches:
|
||||||
|
return ans
|
||||||
|
self._map_filtered = ans
|
||||||
|
|
||||||
|
def search_getting_ids(self, query, search_restriction):
|
||||||
|
q = ''
|
||||||
|
if not query or not query.strip():
|
||||||
|
q = search_restriction
|
||||||
|
else:
|
||||||
|
q = query
|
||||||
|
if search_restriction:
|
||||||
|
q = u'%s (%s)' % (search_restriction, query)
|
||||||
|
if not q:
|
||||||
|
return list(self._map)
|
||||||
|
matches = sorted(self.parse(q))
|
||||||
|
return [id for id in self._map if id in matches]
|
||||||
|
|
||||||
|
def set_search_restriction(self, s):
|
||||||
|
self.search_restriction = s
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
def remove(self, id):
|
def remove(self, id):
|
||||||
self._data[id] = None
|
self._data[id] = None
|
||||||
if id in self._map:
|
if id in self._map:
|
||||||
@ -549,7 +575,9 @@ class ResultCache(SearchQueryParser):
|
|||||||
self.sort(field, ascending)
|
self.sort(field, ascending)
|
||||||
self._map_filtered = list(self._map)
|
self._map_filtered = list(self._map)
|
||||||
if self.search_restriction:
|
if self.search_restriction:
|
||||||
self.search('', return_matches=False, ignore_search_restriction=False)
|
self.search('', return_matches=False)
|
||||||
|
|
||||||
|
# Sorting functions {{{
|
||||||
|
|
||||||
def seriescmp(self, sidx, siidx, x, y, library_order=None):
|
def seriescmp(self, sidx, siidx, x, y, library_order=None):
|
||||||
try:
|
try:
|
||||||
@ -615,24 +643,6 @@ class ResultCache(SearchQueryParser):
|
|||||||
self._map.sort(cmp=fcmp, reverse=not ascending)
|
self._map.sort(cmp=fcmp, reverse=not ascending)
|
||||||
self._map_filtered = [id for id in self._map if id in self._map_filtered]
|
self._map_filtered = [id for id in self._map if id in self._map_filtered]
|
||||||
|
|
||||||
def search(self, query, return_matches=False):
|
# }}}
|
||||||
ans = self.search_getting_ids(query, self.search_restriction)
|
|
||||||
if return_matches:
|
|
||||||
return ans
|
|
||||||
self._map_filtered = ans
|
|
||||||
|
|
||||||
def search_getting_ids(self, query, search_restriction):
|
|
||||||
q = ''
|
|
||||||
if not query or not query.strip():
|
|
||||||
q = search_restriction
|
|
||||||
else:
|
|
||||||
q = query
|
|
||||||
if search_restriction:
|
|
||||||
q = u'%s (%s)' % (search_restriction, query)
|
|
||||||
if not q:
|
|
||||||
return list(self._map)
|
|
||||||
matches = sorted(self.parse(q))
|
|
||||||
return [id for id in self._map if id in matches]
|
|
||||||
|
|
||||||
def set_search_restriction(self, s):
|
|
||||||
self.search_restriction = s
|
|
||||||
|
@ -69,6 +69,8 @@ class FieldMetadata(dict):
|
|||||||
VALID_DATA_TYPES = frozenset([None, 'rating', 'text', 'comments', 'datetime',
|
VALID_DATA_TYPES = frozenset([None, 'rating', 'text', 'comments', 'datetime',
|
||||||
'int', 'float', 'bool', 'series'])
|
'int', 'float', 'bool', 'series'])
|
||||||
|
|
||||||
|
# Builtin metadata {{{
|
||||||
|
|
||||||
_field_metadata = [
|
_field_metadata = [
|
||||||
('authors', {'table':'authors',
|
('authors', {'table':'authors',
|
||||||
'column':'name',
|
'column':'name',
|
||||||
@ -288,6 +290,7 @@ class FieldMetadata(dict):
|
|||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False}),
|
'is_category':False}),
|
||||||
]
|
]
|
||||||
|
# }}}
|
||||||
|
|
||||||
# search labels that are not db columns
|
# search labels that are not db columns
|
||||||
search_items = [ 'all',
|
search_items = [ 'all',
|
||||||
|
@ -54,10 +54,8 @@ def shorten_components_to(length, components):
|
|||||||
r = x[0] if x is components[-1] else ''
|
r = x[0] if x is components[-1] else ''
|
||||||
else:
|
else:
|
||||||
if x is components[-1]:
|
if x is components[-1]:
|
||||||
b, _, e = x.rpartition('.')
|
b, e = os.path.splitext(x)
|
||||||
if not b and e:
|
if e == '.': e = ''
|
||||||
b = e
|
|
||||||
e = ''
|
|
||||||
r = b[:-delta]+e
|
r = b[:-delta]+e
|
||||||
if r.startswith('.'): r = x[0]+r
|
if r.startswith('.'): r = x[0]+r
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user