mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
Searching: Fix escaped parentheses not being correctly handled when parsing search queries. Match books on device: Fix parentheses in search expression not being escaped. Fixes #1255671 [Match Books dialogue doesn't like parentheses](https://bugs.launchpad.net/calibre/+bug/1255671). Match books on device: Fix thumbnail in device metadata cache not being updated when matching books. Fixes #1255676 [[ENHANCEMENT] Match Books to add covers](https://bugs.launchpad.net/calibre/+bug/1255676).
This commit is contained in:
commit
995bbcda49
@ -36,4 +36,4 @@ class MatchBookAction(InterfaceAction):
|
|||||||
return
|
return
|
||||||
|
|
||||||
id_ = view.model().indices(rows)[0]
|
id_ = view.model().indices(rows)[0]
|
||||||
MatchBooks(self.gui, view, id_).exec_()
|
MatchBooks(self.gui, view, id_, rows[0]).exec_()
|
||||||
|
@ -1284,9 +1284,7 @@ class DeviceMixin(object): # {{{
|
|||||||
prefix = ascii_filename(prefix)
|
prefix = ascii_filename(prefix)
|
||||||
names.append('%s_%d%s'%(prefix, id,
|
names.append('%s_%d%s'%(prefix, id,
|
||||||
os.path.splitext(f)[1]))
|
os.path.splitext(f)[1]))
|
||||||
if mi.cover and os.access(mi.cover, os.R_OK):
|
self.update_thumbnail(mi)
|
||||||
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover,
|
|
||||||
'rb').read())
|
|
||||||
dynamic.set('catalogs_to_be_synced', set([]))
|
dynamic.set('catalogs_to_be_synced', set([]))
|
||||||
if files:
|
if files:
|
||||||
remove = []
|
remove = []
|
||||||
@ -1367,9 +1365,7 @@ class DeviceMixin(object): # {{{
|
|||||||
prefix = ascii_filename(prefix)
|
prefix = ascii_filename(prefix)
|
||||||
names.append('%s_%d%s'%(prefix, id,
|
names.append('%s_%d%s'%(prefix, id,
|
||||||
os.path.splitext(f)[1]))
|
os.path.splitext(f)[1]))
|
||||||
if mi.cover and os.access(mi.cover, os.R_OK):
|
self.update_thumbnail(mi)
|
||||||
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover,
|
|
||||||
'rb').read())
|
|
||||||
self.news_to_be_synced = set([])
|
self.news_to_be_synced = set([])
|
||||||
if config['upload_news_to_device'] and files:
|
if config['upload_news_to_device'] and files:
|
||||||
remove = ids if del_on_upload else []
|
remove = ids if del_on_upload else []
|
||||||
@ -1423,8 +1419,7 @@ class DeviceMixin(object): # {{{
|
|||||||
metadata = self.library_view.model().metadata_for(ids)
|
metadata = self.library_view.model().metadata_for(ids)
|
||||||
ids = iter(ids)
|
ids = iter(ids)
|
||||||
for mi in metadata:
|
for mi in metadata:
|
||||||
if mi.cover and os.access(mi.cover, os.R_OK):
|
self.update_thumbnail(mi)
|
||||||
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover, 'rb').read())
|
|
||||||
imetadata = iter(metadata)
|
imetadata = iter(metadata)
|
||||||
|
|
||||||
bad, good, gf, names, remove_ids = [], [], [], [], []
|
bad, good, gf, names, remove_ids = [], [], [], [], []
|
||||||
@ -1665,6 +1660,13 @@ class DeviceMixin(object): # {{{
|
|||||||
loc[4] |= self.book_db_uuid_path_map[id]
|
loc[4] |= self.book_db_uuid_path_map[id]
|
||||||
return loc
|
return loc
|
||||||
|
|
||||||
|
def update_thumbnail(self, book):
|
||||||
|
if book.cover and os.access(book.cover, os.R_OK):
|
||||||
|
book.thumbnail = self.cover_to_thumbnail(open(book.cover, 'rb').read())
|
||||||
|
else:
|
||||||
|
book.thumbnail = self.default_thumbnail
|
||||||
|
|
||||||
|
|
||||||
def set_books_in_library(self, booklists, reset=False, add_as_step_to_job=None,
|
def set_books_in_library(self, booklists, reset=False, add_as_step_to_job=None,
|
||||||
force_send=False):
|
force_send=False):
|
||||||
'''
|
'''
|
||||||
@ -1738,10 +1740,7 @@ class DeviceMixin(object): # {{{
|
|||||||
mi = db.get_metadata(id_, index_is_id=True, get_cover=get_covers)
|
mi = db.get_metadata(id_, index_is_id=True, get_cover=get_covers)
|
||||||
book.smart_update(mi, replace_metadata=True)
|
book.smart_update(mi, replace_metadata=True)
|
||||||
if get_covers and desired_thumbnail_height != 0:
|
if get_covers and desired_thumbnail_height != 0:
|
||||||
if book.cover and os.access(book.cover, os.R_OK):
|
self.update_thumbnail(book)
|
||||||
book.thumbnail = self.cover_to_thumbnail(open(book.cover, 'rb').read())
|
|
||||||
else:
|
|
||||||
book.thumbnail = self.default_thumbnail
|
|
||||||
|
|
||||||
def updateq(id_, book):
|
def updateq(id_, book):
|
||||||
try:
|
try:
|
||||||
|
@ -46,7 +46,7 @@ class TableItem(QTableWidgetItem):
|
|||||||
|
|
||||||
class MatchBooks(QDialog, Ui_MatchBooks):
|
class MatchBooks(QDialog, Ui_MatchBooks):
|
||||||
|
|
||||||
def __init__(self, gui, view, id_):
|
def __init__(self, gui, view, id_, row_index):
|
||||||
QDialog.__init__(self, gui, flags=Qt.Window)
|
QDialog.__init__(self, gui, flags=Qt.Window)
|
||||||
Ui_MatchBooks.__init__(self)
|
Ui_MatchBooks.__init__(self)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@ -73,6 +73,7 @@ class MatchBooks(QDialog, Ui_MatchBooks):
|
|||||||
self.view = view
|
self.view = view
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
self.current_device_book_id = id_
|
self.current_device_book_id = id_
|
||||||
|
self.current_device_book_index = row_index
|
||||||
self.current_library_book_id = None
|
self.current_library_book_id = None
|
||||||
|
|
||||||
# Set up the books table columns
|
# Set up the books table columns
|
||||||
@ -107,7 +108,9 @@ class MatchBooks(QDialog, Ui_MatchBooks):
|
|||||||
self.buttonBox.rejected.connect(self.reject)
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
self.ignore_next_key = False
|
self.ignore_next_key = False
|
||||||
|
|
||||||
self.search_text.setText(self.device_db[self.current_device_book_id].title)
|
search_text= self.device_db[self.current_device_book_id].title
|
||||||
|
search_text = search_text.replace('(', '\\(').replace(')', '\\)')
|
||||||
|
self.search_text.setText(search_text)
|
||||||
|
|
||||||
def return_pressed(self):
|
def return_pressed(self):
|
||||||
self.ignore_next_key = True
|
self.ignore_next_key = True
|
||||||
@ -192,9 +195,14 @@ class MatchBooks(QDialog, Ui_MatchBooks):
|
|||||||
d.exec_()
|
d.exec_()
|
||||||
return
|
return
|
||||||
mi = self.library_db.get_metadata(self.current_library_book_id,
|
mi = self.library_db.get_metadata(self.current_library_book_id,
|
||||||
index_is_id=True, get_user_categories=False)
|
index_is_id=True, get_user_categories=False,
|
||||||
self.device_db[self.current_device_book_id].smart_update(mi, replace_metadata=True)
|
get_cover=True)
|
||||||
self.device_db[self.current_device_book_id].in_library_waiting = True
|
book = self.device_db[self.current_device_book_id]
|
||||||
|
book.smart_update(mi, replace_metadata=True)
|
||||||
|
self.gui.update_thumbnail(book)
|
||||||
|
book.in_library_waiting = True
|
||||||
|
self.view.model().current_changed(self.current_device_book_index,
|
||||||
|
self.current_device_book_index)
|
||||||
self.save_state()
|
self.save_state()
|
||||||
QDialog.accept(self)
|
QDialog.accept(self)
|
||||||
|
|
||||||
|
@ -177,14 +177,17 @@ class Parser(object):
|
|||||||
def parse(self, expr, locations):
|
def parse(self, expr, locations):
|
||||||
self.locations = locations
|
self.locations = locations
|
||||||
|
|
||||||
# Strip out escaped backslashes and escaped quotes so that the
|
# Strip out escaped backslashes, quotes and parens so that the
|
||||||
# lex scanner doesn't get confused. We put them back later.
|
# lex scanner doesn't get confused. We put them back later.
|
||||||
expr = expr.replace(u'\\\\', u'\x01').replace(u'\\"', u'\x02')
|
expr = expr.replace(u'\\\\', u'\x01').replace(u'\\"', u'\x02')
|
||||||
|
expr = expr.replace(u'\\(', u'\x03').replace(u'\\)', u'\x04')
|
||||||
self.tokens = self.lex_scanner.scan(expr)[0]
|
self.tokens = self.lex_scanner.scan(expr)[0]
|
||||||
for (i,tok) in enumerate(self.tokens):
|
for (i,tok) in enumerate(self.tokens):
|
||||||
tt, tv = tok
|
tt, tv = tok
|
||||||
if tt == self.WORD or tt == self.QUOTED_WORD:
|
if tt == self.WORD or tt == self.QUOTED_WORD:
|
||||||
self.tokens[i] = (tt, tv.replace(u'\x01', u'\\').replace(u'\x02', u'"'))
|
self.tokens[i] = (tt,
|
||||||
|
tv.replace(u'\x01', u'\\').replace(u'\x02', u'"').
|
||||||
|
replace(u'\x03', u'(').replace(u'\x04', u')'))
|
||||||
|
|
||||||
self.current_token = 0
|
self.current_token = 0
|
||||||
prog = self.or_expression()
|
prog = self.or_expression()
|
||||||
@ -219,10 +222,10 @@ class Parser(object):
|
|||||||
return self.location_expression()
|
return self.location_expression()
|
||||||
|
|
||||||
def location_expression(self):
|
def location_expression(self):
|
||||||
if self.token() == '(':
|
if self.token_type() == self.OPCODE and self.token() == '(':
|
||||||
self.advance()
|
self.advance()
|
||||||
res = self.or_expression()
|
res = self.or_expression()
|
||||||
if self.token(advance=True) != ')':
|
if self.token_type() != self.OPCODE or self.token(advance=True) != ')':
|
||||||
raise ParseException(_('missing )'))
|
raise ParseException(_('missing )'))
|
||||||
return res
|
return res
|
||||||
if self.token_type() not in (self.WORD, self.QUOTED_WORD):
|
if self.token_type() not in (self.WORD, self.QUOTED_WORD):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user