mirror of
https://github.com/kovidgoyal/calibre.git
synced 2026-05-08 10:32:28 +00:00
collapsible else if (auto-fix)
ruff 'PLR5501'
This commit is contained in:
+1
-1
@@ -114,7 +114,7 @@ select = [
|
||||
'E', 'F', 'I', 'W', 'INT',
|
||||
'Q', 'UP', 'YTT', 'TID', 'C4', 'COM818', 'PIE', 'RET501', 'ISC',
|
||||
'PLE', 'PLW', 'PLC',
|
||||
'PLR0402', 'PLR1711', 'PLR1716', 'PLR1722', 'PLR1733', 'PLR1736', 'PLR1730',
|
||||
'PLR0402', 'PLR1711', 'PLR1716', 'PLR1722', 'PLR1733', 'PLR1736', 'PLR1730', 'PLR5501',
|
||||
'RUF', # note: RUF can flag many unsolicited errors
|
||||
# preview rules
|
||||
'RUF051', 'RUF056', # useless dict operation
|
||||
|
||||
@@ -94,15 +94,14 @@ class brewiarz(BasicNewsRecipe):
|
||||
link_url = url[:-10] + link_url_print
|
||||
current_articles.append({'title': link_title,
|
||||
'url': link_url, 'description': '', 'date': ''})
|
||||
elif link.findParent(name='ol'):
|
||||
continue
|
||||
else:
|
||||
if link.findParent(name='ol'):
|
||||
continue
|
||||
else:
|
||||
link_title = self.tag_to_string(link)
|
||||
link_url_print = link['href'].replace('php3', 'php3?kr=_druk&wr=lg&')
|
||||
link_url = url[:-10] + link_url_print
|
||||
current_articles.append({'title': link_title,
|
||||
'url': link_url, 'description': '', 'date': ''})
|
||||
link_title = self.tag_to_string(link)
|
||||
link_url_print = link['href'].replace('php3', 'php3?kr=_druk&wr=lg&')
|
||||
link_url = url[:-10] + link_url_print
|
||||
current_articles.append({'title': link_title,
|
||||
'url': link_url, 'description': '', 'date': ''})
|
||||
return current_articles
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -55,10 +55,9 @@ class Business_insider(BasicNewsRecipe):
|
||||
for item in soup.findAll('a'):
|
||||
if item['href'].startswith('http://feedads'):
|
||||
item.extract()
|
||||
else:
|
||||
if item.string is not None:
|
||||
tstr = item.string
|
||||
item.replaceWith(tstr)
|
||||
elif item.string is not None:
|
||||
tstr = item.string
|
||||
item.replaceWith(tstr)
|
||||
for item in soup.findAll('img', alt=False):
|
||||
item['alt'] = 'image'
|
||||
return soup
|
||||
|
||||
@@ -95,13 +95,12 @@ class CSMonitor(BasicNewsRecipe):
|
||||
if item.string is not None:
|
||||
str = item.string
|
||||
item.replaceWith(str)
|
||||
elif limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
if limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
for item in soup.findAll('img', src=True):
|
||||
if 'scorecardresearch' in item['src']:
|
||||
item.extract()
|
||||
|
||||
@@ -50,13 +50,12 @@ class FinancialSense(BasicNewsRecipe):
|
||||
if item.string is not None:
|
||||
str = item.string
|
||||
item.replaceWith(str)
|
||||
elif limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
if limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
for item in soup.findAll('img', alt=False):
|
||||
item['alt'] = 'image'
|
||||
return soup
|
||||
|
||||
@@ -76,13 +76,12 @@ class Novosti(BasicNewsRecipe):
|
||||
if item.string is not None:
|
||||
str = item.string
|
||||
item.replaceWith(str)
|
||||
elif limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
if limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
for item in soup.findAll('img', alt=False):
|
||||
item['alt'] = 'image'
|
||||
return soup
|
||||
|
||||
+5
-6
@@ -110,13 +110,12 @@ class Nspm(BasicNewsRecipe):
|
||||
if item.string is not None:
|
||||
str = item.string
|
||||
item.replaceWith(str)
|
||||
elif limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
if limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
for item in soup.findAll('img', alt=False):
|
||||
item['alt'] = 'image'
|
||||
return soup
|
||||
|
||||
@@ -122,10 +122,9 @@ class respektRecipe(BasicNewsRecipe):
|
||||
text = child.text_content()
|
||||
if next.text:
|
||||
next.text = next.text + u' • ' + text
|
||||
else:
|
||||
if next.getchildren():
|
||||
next_child = next.getchildren()[0]
|
||||
next_child.text = next_child.text + u' • ' + text
|
||||
elif next.getchildren():
|
||||
next_child = next.getchildren()[0]
|
||||
next_child.text = next_child.text + u' • ' + text
|
||||
par.getparent().remove(par)
|
||||
# Insert text length
|
||||
text = root.xpath("//div[@id='postcontent']")[0]
|
||||
|
||||
@@ -43,9 +43,8 @@ class monthly(BasicNewsRecipe):
|
||||
for art in main.findAll(**classes('article')):
|
||||
if hr := art.find('a', attrs={'href':lambda x: x and x.startswith('/issue/')}):
|
||||
url = 'https://www.themonthly.com.au' + hr['href']
|
||||
else:
|
||||
if hr := art.findParent('a', attrs={'href':lambda x: x and x.startswith('/issue/')}):
|
||||
url = 'https://www.themonthly.com.au' + hr['href']
|
||||
elif hr := art.findParent('a', attrs={'href':lambda x: x and x.startswith('/issue/')}):
|
||||
url = 'https://www.themonthly.com.au' + hr['href']
|
||||
title = self.tag_to_string(art.find(**classes('article__title')))
|
||||
desc = ''
|
||||
if text := art.find(**classes('article__text')):
|
||||
|
||||
@@ -55,13 +55,12 @@ class Variety(BasicNewsRecipe):
|
||||
if item.string is not None:
|
||||
str = item.string
|
||||
item.replaceWith(str)
|
||||
elif limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
if limg:
|
||||
item.name = 'div'
|
||||
item.attrs = []
|
||||
else:
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
str = self.tag_to_string(item)
|
||||
item.replaceWith(str)
|
||||
for item in soup.findAll('img', alt=False):
|
||||
item['alt'] = 'image'
|
||||
return soup
|
||||
|
||||
+6
-7
@@ -105,14 +105,13 @@ def expand_file_list(items, is_paths=True, cross_compile_for='native'):
|
||||
items = [f'bypy/b/windows/64/{pkg}/{category}']
|
||||
items = expand_file_list(item, is_paths=is_paths, cross_compile_for=cross_compile_for)
|
||||
ans.extend(items)
|
||||
elif '*' in item:
|
||||
ans.extend(expand_file_list(sorted(glob.glob(os.path.join(SRC, item))), is_paths=is_paths, cross_compile_for=cross_compile_for))
|
||||
else:
|
||||
if '*' in item:
|
||||
ans.extend(expand_file_list(sorted(glob.glob(os.path.join(SRC, item))), is_paths=is_paths, cross_compile_for=cross_compile_for))
|
||||
else:
|
||||
item = [item]
|
||||
if is_paths:
|
||||
item = absolutize(item)
|
||||
ans.extend(item)
|
||||
item = [item]
|
||||
if is_paths:
|
||||
item = absolutize(item)
|
||||
ans.extend(item)
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
+3
-4
@@ -383,11 +383,10 @@ class Bootstrap(Command):
|
||||
clone_cmd.insert(2, '--depth=1')
|
||||
subprocess.check_call(clone_cmd, cwd=self.d(self.SRC))
|
||||
print(f'Downloaded translations in {int(time.time() - st)} seconds')
|
||||
elif os.path.exists(tdir):
|
||||
subprocess.check_call(['git', 'pull'], cwd=tdir)
|
||||
else:
|
||||
if os.path.exists(tdir):
|
||||
subprocess.check_call(['git', 'pull'], cwd=tdir)
|
||||
else:
|
||||
subprocess.check_call(clone_cmd, cwd=self.d(self.SRC))
|
||||
subprocess.check_call(clone_cmd, cwd=self.d(self.SRC))
|
||||
|
||||
def run(self, opts):
|
||||
self.info(f'\n\nAll done! You should now be able to run "{sys.executable} setup.py install" to install calibre')
|
||||
|
||||
@@ -353,10 +353,9 @@ class CalibrePluginFinder:
|
||||
plugin_name = f'dummy{c}'
|
||||
if plugin_name not in self.loaded_plugins:
|
||||
break
|
||||
else:
|
||||
if self._identifier_pat.match(plugin_name) is None:
|
||||
raise InvalidPlugin(
|
||||
f'The plugin at {path_to_zip_file!r} uses an invalid import name: {plugin_name!r}')
|
||||
elif self._identifier_pat.match(plugin_name) is None:
|
||||
raise InvalidPlugin(
|
||||
f'The plugin at {path_to_zip_file!r} uses an invalid import name: {plugin_name!r}')
|
||||
|
||||
pynames = [x for x in names if x.endswith('.py')]
|
||||
|
||||
|
||||
+66
-70
@@ -969,11 +969,10 @@ class DB:
|
||||
metadata['column'] = 'extra'
|
||||
metadata['table'] = link_table
|
||||
tables[label] = OneToOneTable(label, metadata)
|
||||
elif data['datatype'] == 'composite':
|
||||
tables[label] = CompositeTable(label, metadata)
|
||||
else:
|
||||
if data['datatype'] == 'composite':
|
||||
tables[label] = CompositeTable(label, metadata)
|
||||
else:
|
||||
tables[label] = OneToOneTable(label, metadata)
|
||||
tables[label] = OneToOneTable(label, metadata)
|
||||
|
||||
self.FIELD_MAP['ondevice'] = base = base+1
|
||||
self.field_metadata.set_field_record_index('ondevice', base, prefer_custom=False)
|
||||
@@ -1734,34 +1733,33 @@ class DB:
|
||||
if os.access(path, os.R_OK) and dest and not samefile(dest, path):
|
||||
windows_atomic_move.copy_path_to(path, dest)
|
||||
return True
|
||||
else:
|
||||
if os.access(path, os.R_OK):
|
||||
try:
|
||||
f = open(path, 'rb')
|
||||
except OSError:
|
||||
if iswindows:
|
||||
time.sleep(0.2)
|
||||
f = open(path, 'rb')
|
||||
with f:
|
||||
if hasattr(dest, 'write'):
|
||||
if report_file_size is not None:
|
||||
f.seek(0, os.SEEK_END)
|
||||
report_file_size(f.tell())
|
||||
f.seek(0)
|
||||
shutil.copyfileobj(f, dest)
|
||||
if hasattr(dest, 'flush'):
|
||||
dest.flush()
|
||||
return True
|
||||
elif dest and not samefile(dest, path):
|
||||
if use_hardlink:
|
||||
try:
|
||||
hardlink_file(path, dest)
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
with open(dest, 'wb') as d:
|
||||
shutil.copyfileobj(f, d)
|
||||
return True
|
||||
elif os.access(path, os.R_OK):
|
||||
try:
|
||||
f = open(path, 'rb')
|
||||
except OSError:
|
||||
if iswindows:
|
||||
time.sleep(0.2)
|
||||
f = open(path, 'rb')
|
||||
with f:
|
||||
if hasattr(dest, 'write'):
|
||||
if report_file_size is not None:
|
||||
f.seek(0, os.SEEK_END)
|
||||
report_file_size(f.tell())
|
||||
f.seek(0)
|
||||
shutil.copyfileobj(f, dest)
|
||||
if hasattr(dest, 'flush'):
|
||||
dest.flush()
|
||||
return True
|
||||
elif dest and not samefile(dest, path):
|
||||
if use_hardlink:
|
||||
try:
|
||||
hardlink_file(path, dest)
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
with open(dest, 'wb') as d:
|
||||
shutil.copyfileobj(f, d)
|
||||
return True
|
||||
return False
|
||||
|
||||
def cover_or_cache(self, path, timestamp, as_what='bytes'):
|
||||
@@ -1821,18 +1819,17 @@ class DB:
|
||||
if iswindows:
|
||||
time.sleep(0.2)
|
||||
os.remove(path)
|
||||
elif no_processing:
|
||||
with open(path, 'wb') as f:
|
||||
f.write(data)
|
||||
else:
|
||||
if no_processing:
|
||||
with open(path, 'wb') as f:
|
||||
f.write(data)
|
||||
else:
|
||||
from calibre.utils.img import save_cover_data_to
|
||||
try:
|
||||
save_cover_data_to(data, path)
|
||||
except OSError:
|
||||
if iswindows:
|
||||
time.sleep(0.2)
|
||||
save_cover_data_to(data, path)
|
||||
from calibre.utils.img import save_cover_data_to
|
||||
try:
|
||||
save_cover_data_to(data, path)
|
||||
except OSError:
|
||||
if iswindows:
|
||||
time.sleep(0.2)
|
||||
save_cover_data_to(data, path)
|
||||
|
||||
def copy_format_to(self, book_id, fmt, fname, path, dest,
|
||||
windows_atomic_move=None, use_hardlink=False, report_file_size=None):
|
||||
@@ -1853,33 +1850,32 @@ class DB:
|
||||
pass # Nothing too catastrophic happened, the cases mismatch, that's all
|
||||
else:
|
||||
windows_atomic_move.copy_path_to(path, dest)
|
||||
else:
|
||||
if hasattr(dest, 'write'):
|
||||
with open(path, 'rb') as f:
|
||||
if report_file_size is not None:
|
||||
f.seek(0, os.SEEK_END)
|
||||
report_file_size(f.tell())
|
||||
f.seek(0)
|
||||
shutil.copyfileobj(f, dest)
|
||||
if hasattr(dest, 'flush'):
|
||||
dest.flush()
|
||||
elif dest:
|
||||
if samefile(dest, path):
|
||||
if not self.is_case_sensitive and path != dest:
|
||||
# Ensure that the file has the same case as dest
|
||||
try:
|
||||
os.rename(path, dest)
|
||||
except OSError:
|
||||
pass # Nothing too catastrophic happened, the cases mismatch, that's all
|
||||
else:
|
||||
if use_hardlink:
|
||||
try:
|
||||
hardlink_file(path, dest)
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
with open(path, 'rb') as f, open(make_long_path_useable(dest), 'wb') as d:
|
||||
shutil.copyfileobj(f, d)
|
||||
elif hasattr(dest, 'write'):
|
||||
with open(path, 'rb') as f:
|
||||
if report_file_size is not None:
|
||||
f.seek(0, os.SEEK_END)
|
||||
report_file_size(f.tell())
|
||||
f.seek(0)
|
||||
shutil.copyfileobj(f, dest)
|
||||
if hasattr(dest, 'flush'):
|
||||
dest.flush()
|
||||
elif dest:
|
||||
if samefile(dest, path):
|
||||
if not self.is_case_sensitive and path != dest:
|
||||
# Ensure that the file has the same case as dest
|
||||
try:
|
||||
os.rename(path, dest)
|
||||
except OSError:
|
||||
pass # Nothing too catastrophic happened, the cases mismatch, that's all
|
||||
else:
|
||||
if use_hardlink:
|
||||
try:
|
||||
hardlink_file(path, dest)
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
with open(path, 'rb') as f, open(make_long_path_useable(dest), 'wb') as d:
|
||||
shutil.copyfileobj(f, d)
|
||||
return True
|
||||
|
||||
def windows_check_if_files_in_use(self, paths):
|
||||
|
||||
@@ -89,11 +89,10 @@ def do_adding(db, request_id, notify_changes, is_remote, mi, format_map, add_dup
|
||||
duplicates.append((mi, {x: format_map[x] for x in duplicated_formats}))
|
||||
else:
|
||||
add_book()
|
||||
elif identical_book_list:
|
||||
duplicates.append((mi, format_map))
|
||||
else:
|
||||
if identical_book_list:
|
||||
duplicates.append((mi, format_map))
|
||||
else:
|
||||
add_book()
|
||||
add_book()
|
||||
if added_ids and identical_books_data is not None:
|
||||
for book_id in added_ids:
|
||||
db.update_data_for_find_identical_books(book_id, identical_books_data)
|
||||
@@ -221,11 +220,10 @@ def do_add(
|
||||
path = os.path.abspath(path)
|
||||
if os.path.isdir(path):
|
||||
dirs.append(path)
|
||||
elif os.path.exists(path):
|
||||
files.append(path)
|
||||
else:
|
||||
if os.path.exists(path):
|
||||
files.append(path)
|
||||
else:
|
||||
prints(path, 'not found')
|
||||
prints(path, 'not found')
|
||||
|
||||
file_duplicates, added_ids, merged_ids = [], set(), set()
|
||||
for book in files:
|
||||
|
||||
+10
-13
@@ -347,19 +347,16 @@ class BooleanSearch: # {{{
|
||||
if val is None or not val: # item is None or set to false
|
||||
if query in {self.local_no, self.local_unchecked, 'unchecked', '_unchecked', 'no', '_no', 'false'}:
|
||||
matches |= book_ids
|
||||
else: # item is explicitly set to true
|
||||
if query in {self.local_yes, self.local_checked, 'checked', '_checked', 'yes', '_yes', 'true'}:
|
||||
matches |= book_ids
|
||||
else:
|
||||
if val is None:
|
||||
if query in {self.local_empty, self.local_blank, 'blank', '_blank', 'empty', '_empty', 'false'}:
|
||||
matches |= book_ids
|
||||
elif not val: # is not None and false
|
||||
if query in {self.local_no, self.local_unchecked, 'unchecked', '_unchecked', 'no', '_no', 'true'}:
|
||||
matches |= book_ids
|
||||
else: # item is not None and true
|
||||
if query in {self.local_yes, self.local_checked, 'checked', '_checked', 'yes', '_yes', 'true'}:
|
||||
matches |= book_ids
|
||||
elif query in {self.local_yes, self.local_checked, 'checked', '_checked', 'yes', '_yes', 'true'}:
|
||||
matches |= book_ids
|
||||
elif val is None:
|
||||
if query in {self.local_empty, self.local_blank, 'blank', '_blank', 'empty', '_empty', 'false'}:
|
||||
matches |= book_ids
|
||||
elif not val: # is not None and false
|
||||
if query in {self.local_no, self.local_unchecked, 'unchecked', '_unchecked', 'no', '_no', 'true'}:
|
||||
matches |= book_ids
|
||||
elif query in {self.local_yes, self.local_checked, 'checked', '_checked', 'yes', '_yes', 'true'}:
|
||||
matches |= book_ids
|
||||
return matches
|
||||
|
||||
# }}}
|
||||
|
||||
@@ -118,17 +118,16 @@ class Bookmark: # {{{
|
||||
# start//MAGIC_MOBI_CONSTANT + 1))
|
||||
user_notes[start]['displayed_location'] = start // MAGIC_MOBI_CONSTANT + 1
|
||||
user_notes.pop(end_loc)
|
||||
else:
|
||||
# If a bookmark coincides with a user annotation, the locs could
|
||||
# be the same - cheat by nudging -1
|
||||
# Skip bookmark for last_read_location
|
||||
if end_loc != self.last_read:
|
||||
# print(' adding Bookmark at 0x%x (%d)' % (end_loc, end_loc/MAGIC_MOBI_CONSTANT + 1))
|
||||
displayed_location = end_loc // MAGIC_MOBI_CONSTANT + 1
|
||||
user_notes[end_loc - 1] = {'id': self.id,
|
||||
'displayed_location': displayed_location,
|
||||
'type': 'Bookmark',
|
||||
'text': None}
|
||||
# If a bookmark coincides with a user annotation, the locs could
|
||||
# be the same - cheat by nudging -1
|
||||
# Skip bookmark for last_read_location
|
||||
elif end_loc != self.last_read:
|
||||
# print(' adding Bookmark at 0x%x (%d)' % (end_loc, end_loc/MAGIC_MOBI_CONSTANT + 1))
|
||||
displayed_location = end_loc // MAGIC_MOBI_CONSTANT + 1
|
||||
user_notes[end_loc - 1] = {'id': self.id,
|
||||
'displayed_location': displayed_location,
|
||||
'type': 'Bookmark',
|
||||
'text': None}
|
||||
rec_len, = unpack('>I', data[eo+4:eo+8])
|
||||
eo += rec_len + 8
|
||||
sig = data[eo:eo+4]
|
||||
|
||||
@@ -296,17 +296,16 @@ class KINDLE(USBMS):
|
||||
text=(user_notes[location]['text'] if
|
||||
user_notes[location]['type'] == 'Note' else
|
||||
'<i>{}</i>'.format(user_notes[location]['text']))))
|
||||
elif bookmark.book_format == 'pdf':
|
||||
annotations.append(
|
||||
_('<b>Page %(dl)d • %(typ)s</b><br />') % dict(
|
||||
dl=user_notes[location]['displayed_location'],
|
||||
typ=user_notes[location]['type']))
|
||||
else:
|
||||
if bookmark.book_format == 'pdf':
|
||||
annotations.append(
|
||||
_('<b>Page %(dl)d • %(typ)s</b><br />') % dict(
|
||||
dl=user_notes[location]['displayed_location'],
|
||||
typ=user_notes[location]['type']))
|
||||
else:
|
||||
annotations.append(
|
||||
_('<b>Location %(dl)d • %(typ)s</b><br />') % dict(
|
||||
dl=user_notes[location]['displayed_location'],
|
||||
typ=user_notes[location]['type']))
|
||||
annotations.append(
|
||||
_('<b>Location %(dl)d • %(typ)s</b><br />') % dict(
|
||||
dl=user_notes[location]['displayed_location'],
|
||||
typ=user_notes[location]['type']))
|
||||
|
||||
for annotation in annotations:
|
||||
annot = BeautifulSoup('<span>' + annotation + '</span>').find('span')
|
||||
|
||||
@@ -268,10 +268,9 @@ class KTCollectionsBookList(CollectionsBookList):
|
||||
if fm['datatype'] == 'text' and len(category) > 1 and \
|
||||
category[0] == '[' and category[-1] == ']':
|
||||
continue
|
||||
else: # is a standard field
|
||||
if attr == 'tags' and len(category) > 1 and \
|
||||
category[0] == '[' and category[-1] == ']':
|
||||
continue
|
||||
elif attr == 'tags' and len(category) > 1 and \
|
||||
category[0] == '[' and category[-1] == ']':
|
||||
continue
|
||||
|
||||
# The category should not be None, but, it has happened.
|
||||
if not category:
|
||||
|
||||
@@ -703,26 +703,25 @@ class KOBO(USBMS):
|
||||
elif oncard == 'carda':
|
||||
path = path.replace('file:///mnt/sd/', self._card_a_prefix)
|
||||
# print('SD Card: ' + path)
|
||||
else:
|
||||
if ContentType == '6' and MimeType == 'Shortcover':
|
||||
# This is a hack as the kobo files do not exist
|
||||
# but the path is required to make a unique id
|
||||
# for calibre's reference
|
||||
path = self._main_prefix + path + '.kobo'
|
||||
# print('Path: ' + path)
|
||||
elif (ContentType == '6' or ContentType == '10') and (
|
||||
MimeType == 'application/x-kobo-epub+zip' or (
|
||||
MimeType == 'application/epub+zip' and self.isTolinoDevice())
|
||||
):
|
||||
if path.startswith('file:///mnt/onboard/'):
|
||||
path = self._main_prefix + path.replace('file:///mnt/onboard/', '')
|
||||
else:
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/kepub/' + path
|
||||
# print('Internal: ' + path)
|
||||
elif ContentType == '6' and MimeType == 'Shortcover':
|
||||
# This is a hack as the kobo files do not exist
|
||||
# but the path is required to make a unique id
|
||||
# for calibre's reference
|
||||
path = self._main_prefix + path + '.kobo'
|
||||
# print('Path: ' + path)
|
||||
elif (ContentType == '6' or ContentType == '10') and (
|
||||
MimeType == 'application/x-kobo-epub+zip' or (
|
||||
MimeType == 'application/epub+zip' and self.isTolinoDevice())
|
||||
):
|
||||
if path.startswith('file:///mnt/onboard/'):
|
||||
path = self._main_prefix + path.replace('file:///mnt/onboard/', '')
|
||||
else:
|
||||
# if path.startswith('file:///mnt/onboard/'):
|
||||
path = path.replace('file:///mnt/onboard/', self._main_prefix)
|
||||
path = path.replace('/mnt/onboard/', self._main_prefix)
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/kepub/' + path
|
||||
# print('Internal: ' + path)
|
||||
else:
|
||||
# if path.startswith('file:///mnt/onboard/'):
|
||||
path = path.replace('file:///mnt/onboard/', self._main_prefix)
|
||||
path = path.replace('/mnt/onboard/', self._main_prefix)
|
||||
# print('Internal: ' + path)
|
||||
|
||||
return path
|
||||
@@ -2193,25 +2192,24 @@ class KOBOTOUCH(KOBO):
|
||||
|
||||
if oncard == 'cardb':
|
||||
print('path from_contentid cardb')
|
||||
else:
|
||||
if (ContentType == '6' or ContentType == '10'):
|
||||
if (MimeType == 'application/octet-stream'): # Audiobooks purchased from Kobo are in a different location.
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/audiobook/' + path
|
||||
elif (MimeType == 'audio/mpeg' and self.isTolinoDevice()):
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/audiobook/' + path
|
||||
elif path.startswith('file:///mnt/onboard/'):
|
||||
path = self._main_prefix + path.replace('file:///mnt/onboard/', '')
|
||||
elif path.startswith('file:///mnt/sd/'):
|
||||
path = self._card_a_prefix + path.replace('file:///mnt/sd/', '')
|
||||
elif externalId:
|
||||
path = self._card_a_prefix + 'koboExtStorage/kepub/' + path
|
||||
else:
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/kepub/' + path
|
||||
else: # Should never get here, but, just in case...
|
||||
# if path.startswith('file:///mnt/onboard/'):
|
||||
path = path.replace('file:///mnt/onboard/', self._main_prefix)
|
||||
path = path.replace('file:///mnt/sd/', self._card_a_prefix)
|
||||
path = path.replace('/mnt/onboard/', self._main_prefix)
|
||||
elif (ContentType == '6' or ContentType == '10'):
|
||||
if (MimeType == 'application/octet-stream'): # Audiobooks purchased from Kobo are in a different location.
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/audiobook/' + path
|
||||
elif (MimeType == 'audio/mpeg' and self.isTolinoDevice()):
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/audiobook/' + path
|
||||
elif path.startswith('file:///mnt/onboard/'):
|
||||
path = self._main_prefix + path.replace('file:///mnt/onboard/', '')
|
||||
elif path.startswith('file:///mnt/sd/'):
|
||||
path = self._card_a_prefix + path.replace('file:///mnt/sd/', '')
|
||||
elif externalId:
|
||||
path = self._card_a_prefix + 'koboExtStorage/kepub/' + path
|
||||
else:
|
||||
path = self._main_prefix + KOBO_ROOT_DIR_NAME + '/kepub/' + path
|
||||
else: # Should never get here, but, just in case...
|
||||
# if path.startswith('file:///mnt/onboard/'):
|
||||
path = path.replace('file:///mnt/onboard/', self._main_prefix)
|
||||
path = path.replace('file:///mnt/sd/', self._card_a_prefix)
|
||||
path = path.replace('/mnt/onboard/', self._main_prefix)
|
||||
# print('Internal: ' + path)
|
||||
|
||||
return path
|
||||
@@ -2730,9 +2728,8 @@ class KOBOTOUCH(KOBO):
|
||||
if show_debug:
|
||||
debug_print(' adding category to book.device_collections', book.device_collections)
|
||||
book.device_collections.append(category)
|
||||
else:
|
||||
if show_debug:
|
||||
debug_print(' category not added to book.device_collections', book.device_collections)
|
||||
elif show_debug:
|
||||
debug_print(' category not added to book.device_collections', book.device_collections)
|
||||
debug_print(f"KoboTouch:update_device_database_collections - end for category='{category}'")
|
||||
|
||||
elif have_bookshelf_attributes: # No collections but have set the shelf option
|
||||
@@ -3306,11 +3303,10 @@ class KOBOTOUCH(KOBO):
|
||||
if ContentID is not None:
|
||||
query += ' WHERE ContentId = ?'
|
||||
values.append(ContentID)
|
||||
else:
|
||||
if oncard == 'carda':
|
||||
query += " WHERE ContentID like 'file:///mnt/sd/%'"
|
||||
elif oncard != 'carda' and oncard != 'cardb':
|
||||
query += " WHERE ContentID not like 'file:///mnt/sd/%'"
|
||||
elif oncard == 'carda':
|
||||
query += " WHERE ContentID like 'file:///mnt/sd/%'"
|
||||
elif oncard != 'carda' and oncard != 'cardb':
|
||||
query += " WHERE ContentID not like 'file:///mnt/sd/%'"
|
||||
|
||||
if bookshelves:
|
||||
placeholder = '?'
|
||||
|
||||
@@ -277,13 +277,12 @@ class PRS505(USBMS):
|
||||
prefix = None
|
||||
if is_main:
|
||||
prefix = self._main_prefix
|
||||
else:
|
||||
if self._card_a_prefix and \
|
||||
path.startswith(self._card_a_prefix):
|
||||
prefix = self._card_a_prefix
|
||||
elif self._card_b_prefix and \
|
||||
path.startswith(self._card_b_prefix):
|
||||
prefix = self._card_b_prefix
|
||||
elif self._card_a_prefix and \
|
||||
path.startswith(self._card_a_prefix):
|
||||
prefix = self._card_a_prefix
|
||||
elif self._card_b_prefix and \
|
||||
path.startswith(self._card_b_prefix):
|
||||
prefix = self._card_b_prefix
|
||||
if prefix is None:
|
||||
prints('WARNING: Failed to find prefix for:', filepath)
|
||||
return
|
||||
|
||||
@@ -465,11 +465,10 @@ class PRST1(USBMS):
|
||||
author = newmi.author_sort
|
||||
else:
|
||||
author = authors_to_sort_string(newmi.authors)
|
||||
elif use_sony_authors:
|
||||
author = newmi.authors[0]
|
||||
else:
|
||||
if use_sony_authors:
|
||||
author = newmi.authors[0]
|
||||
else:
|
||||
author = authors_to_string(newmi.authors)
|
||||
author = authors_to_string(newmi.authors)
|
||||
except Exception:
|
||||
author = _('Unknown')
|
||||
title = newmi.title or _('Unknown')
|
||||
|
||||
@@ -285,9 +285,8 @@ class CollectionsBookList(BookList):
|
||||
else:
|
||||
collections[cat_name][lpath] = \
|
||||
(book, book.get(attr+'_index', sys.maxsize), tsval)
|
||||
else:
|
||||
if lpath not in collections[cat_name]:
|
||||
collections[cat_name][lpath] = (book, tsval, tsval)
|
||||
elif lpath not in collections[cat_name]:
|
||||
collections[cat_name][lpath] = (book, tsval, tsval)
|
||||
|
||||
# All books by author
|
||||
if all_by_author:
|
||||
|
||||
@@ -248,10 +248,9 @@ class USBMS(CLI, Device):
|
||||
if self.update_metadata_item(bl[idx]):
|
||||
# print('update_metadata_item returned true')
|
||||
changed = True
|
||||
else:
|
||||
if bl.add_book(self.book_from_path(prefix, lpath),
|
||||
replace_metadata=False):
|
||||
changed = True
|
||||
elif bl.add_book(self.book_from_path(prefix, lpath),
|
||||
replace_metadata=False):
|
||||
changed = True
|
||||
except Exception: # Probably a filename encoding error
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -70,9 +70,8 @@ def replace_encoding_declarations(raw, enc='utf-8', limit=50*1024):
|
||||
if is_binary:
|
||||
if not isinstance(enc, bytes):
|
||||
enc = enc.encode('ascii')
|
||||
else:
|
||||
if isinstance(enc, bytes):
|
||||
enc = enc.decode('ascii')
|
||||
elif isinstance(enc, bytes):
|
||||
enc = enc.decode('ascii')
|
||||
|
||||
def sub(m):
|
||||
ans = m.group()
|
||||
|
||||
@@ -213,9 +213,8 @@ class PageProcessor(list): # {{{
|
||||
# to leave it as original size
|
||||
img = resize_image(img, newsizex, newsizey)
|
||||
img = add_borders_to_image(img, left=deltax, right=deltax, top=deltay, bottom=deltay)
|
||||
else:
|
||||
if SCRWIDTH < MAX_SCREEN_SIZE and SCRHEIGHT < MAX_SCREEN_SIZE:
|
||||
img = resize_image(img, SCRWIDTH, SCRHEIGHT)
|
||||
elif SCRWIDTH < MAX_SCREEN_SIZE and SCRHEIGHT < MAX_SCREEN_SIZE:
|
||||
img = resize_image(img, SCRWIDTH, SCRHEIGHT)
|
||||
|
||||
if not self.opts.dont_sharpen:
|
||||
img = gaussian_sharpen_image(img, 0.0, 1.0)
|
||||
|
||||
@@ -92,11 +92,10 @@ def option_recommendation_to_cli_option(add_option, rec):
|
||||
if isinstance(rec.recommended_value, bool):
|
||||
attrs['action'] = 'store_false' if rec.recommended_value else \
|
||||
'store_true'
|
||||
else:
|
||||
if isinstance(rec.recommended_value, numbers.Integral):
|
||||
attrs['type'] = 'int'
|
||||
elif isinstance(rec.recommended_value, numbers.Real):
|
||||
attrs['type'] = 'float'
|
||||
elif isinstance(rec.recommended_value, numbers.Integral):
|
||||
attrs['type'] = 'int'
|
||||
elif isinstance(rec.recommended_value, numbers.Real):
|
||||
attrs['type'] = 'float'
|
||||
|
||||
if opt.long_switch == 'verbose':
|
||||
attrs['action'] = 'count'
|
||||
|
||||
@@ -281,11 +281,10 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
encryption = self.encrypt_fonts(encrypted_fonts, tdir, uuid)
|
||||
if self.opts.epub_version == '3':
|
||||
encryption = self.upgrade_to_epub3(tdir, opf, encryption)
|
||||
else:
|
||||
if cb := getattr(self, 'container_callback', None):
|
||||
container, cxpath, encpath = self.create_container(tdir, opf, encryption)
|
||||
cb(container)
|
||||
encryption = self.end_container(cxpath, encpath)
|
||||
elif cb := getattr(self, 'container_callback', None):
|
||||
container, cxpath, encpath = self.create_container(tdir, opf, encryption)
|
||||
cb(container)
|
||||
encryption = self.end_container(cxpath, encpath)
|
||||
|
||||
from calibre.ebooks.epub import initialize_container
|
||||
with initialize_container(output_path, os.path.basename(opf),
|
||||
|
||||
@@ -142,23 +142,21 @@ class SNBOutput(OutputFormatPlugin):
|
||||
item = tocitem.href.split('#')
|
||||
if len(item) != 2:
|
||||
log.error(f'Error in TOC item: {tocitem}')
|
||||
elif item[0] in outputFiles:
|
||||
outputFiles[item[0]].append((item[1], tocitem.title))
|
||||
else:
|
||||
if item[0] in outputFiles:
|
||||
outputFiles[item[0]].append((item[1], tocitem.title))
|
||||
else:
|
||||
outputFiles[item[0]] = []
|
||||
if '' not in outputFiles[item[0]]:
|
||||
outputFiles[item[0]].append(('', tocitem.title + _(' (Preface)')))
|
||||
ch = etree.SubElement(tocBody, 'chapter')
|
||||
ch.set('src', ProcessFileName(item[0]) + '.snbc')
|
||||
ch.text = tocitem.title + _(' (Preface)')
|
||||
outputFiles[item[0]].append((item[1], tocitem.title))
|
||||
outputFiles[item[0]] = []
|
||||
if '' not in outputFiles[item[0]]:
|
||||
outputFiles[item[0]].append(('', tocitem.title + _(' (Preface)')))
|
||||
ch = etree.SubElement(tocBody, 'chapter')
|
||||
ch.set('src', ProcessFileName(item[0]) + '.snbc')
|
||||
ch.text = tocitem.title + _(' (Preface)')
|
||||
outputFiles[item[0]].append((item[1], tocitem.title))
|
||||
elif tocitem.href in outputFiles:
|
||||
outputFiles[tocitem.href].append(('', tocitem.title))
|
||||
else:
|
||||
if tocitem.href in outputFiles:
|
||||
outputFiles[tocitem.href].append(('', tocitem.title))
|
||||
else:
|
||||
outputFiles[tocitem.href] = []
|
||||
outputFiles[tocitem.href].append(('', tocitem.title))
|
||||
outputFiles[tocitem.href] = []
|
||||
outputFiles[tocitem.href].append(('', tocitem.title))
|
||||
ch = etree.SubElement(tocBody, 'chapter')
|
||||
ch.set('src', ProcessFileName(tocitem.href) + '.snbc')
|
||||
ch.text = tocitem.title
|
||||
@@ -178,12 +176,11 @@ class SNBOutput(OutputFormatPlugin):
|
||||
if item.href not in outputFiles:
|
||||
log.debug(f'File {item.href} is unused in TOC. Continue in last chapter')
|
||||
mergeLast = True
|
||||
else:
|
||||
if oldTree is not None and mergeLast:
|
||||
log.debug(f'Output the modified chapter again: {lastName}')
|
||||
with open(os.path.join(snbcDir, lastName), 'wb') as f:
|
||||
f.write(etree.tostring(oldTree, pretty_print=True, encoding='utf-8'))
|
||||
mergeLast = False
|
||||
elif oldTree is not None and mergeLast:
|
||||
log.debug(f'Output the modified chapter again: {lastName}')
|
||||
with open(os.path.join(snbcDir, lastName), 'wb') as f:
|
||||
f.write(etree.tostring(oldTree, pretty_print=True, encoding='utf-8'))
|
||||
mergeLast = False
|
||||
|
||||
log.debug(f'Converting {item.href} to snbc...')
|
||||
snbwriter = SNBMLizer(log)
|
||||
|
||||
@@ -96,11 +96,10 @@ class HeuristicProcessor:
|
||||
return '<'+tag+' '+pstyle+'>'
|
||||
else:
|
||||
return '<'+tag+' '+pstyle+'>'+span
|
||||
elif not span:
|
||||
return '<'+tag+' style="text-indent:3%">'
|
||||
else:
|
||||
if not span:
|
||||
return '<'+tag+' style="text-indent:3%">'
|
||||
else:
|
||||
return '<'+tag+' style="text-indent:3%">'+span
|
||||
return '<'+tag+' style="text-indent:3%">'+span
|
||||
|
||||
def no_markup(self, raw, percent):
|
||||
'''
|
||||
|
||||
@@ -118,9 +118,8 @@ def parse_text_formatting(text):
|
||||
r[-1] = offset - r[-2]
|
||||
if r[-1] > 0:
|
||||
ranges.append(r)
|
||||
else:
|
||||
if tag in {'b', 'strong', 'i', 'em'}:
|
||||
open_ranges.append([tag, offset, -1])
|
||||
elif tag in {'b', 'strong', 'i', 'em'}:
|
||||
open_ranges.append([tag, offset, -1])
|
||||
else:
|
||||
offset += len(tok.replace('&', '&'))
|
||||
text.append(tok)
|
||||
|
||||
@@ -138,9 +138,8 @@ class Fields:
|
||||
self.fields.append(field)
|
||||
for r in self.namespace.XPath('descendant::w:r')(elem):
|
||||
field.contents.append(r)
|
||||
else:
|
||||
if stack:
|
||||
stack[-1].contents.append(elem)
|
||||
elif stack:
|
||||
stack[-1].contents.append(elem)
|
||||
|
||||
field_types = ('hyperlink', 'xe', 'index', 'ref', 'noteref')
|
||||
parsers = {x.upper():getattr(self, 'parse_'+x) for x in field_types}
|
||||
|
||||
@@ -827,9 +827,8 @@ class Convert:
|
||||
border_style.margin_top, style.margin_top = style.margin_top, inherit
|
||||
if p is not run[-1]:
|
||||
style.padding_bottom = 0
|
||||
else:
|
||||
if has_visible_border:
|
||||
border_style.margin_bottom, style.margin_bottom = style.margin_bottom, inherit
|
||||
elif has_visible_border:
|
||||
border_style.margin_bottom, style.margin_bottom = style.margin_bottom, inherit
|
||||
style.clear_borders()
|
||||
if p is not run[-1]:
|
||||
style.apply_between_border()
|
||||
|
||||
@@ -113,24 +113,23 @@ class TextRun:
|
||||
makeelement(r, 'w:br', w_clear=preserve_whitespace)
|
||||
elif hasattr(text, 'xpath'):
|
||||
r.append(text)
|
||||
elif text:
|
||||
for x in self.soft_hyphen_pat.split(text):
|
||||
if x == '\u00ad':
|
||||
# trailing spaces in <w:t> before a soft hyphen are
|
||||
# ignored, so put them in a preserve whitespace
|
||||
# element with a single space.
|
||||
if not preserve_whitespace and len(r) and r[-1].text and r[-1].text.endswith(' '):
|
||||
r[-1].text = r[-1].text.rstrip()
|
||||
add_text(' ', True)
|
||||
makeelement(r, 'w:softHyphen')
|
||||
elif x:
|
||||
if not preserve_whitespace and x.startswith(' ') and len(r) and r[-1].tag and 'softHyphen' in r[-1].tag:
|
||||
x = x.lstrip()
|
||||
add_text(' ', True)
|
||||
add_text(x, preserve_whitespace)
|
||||
else:
|
||||
if text:
|
||||
for x in self.soft_hyphen_pat.split(text):
|
||||
if x == '\u00ad':
|
||||
# trailing spaces in <w:t> before a soft hyphen are
|
||||
# ignored, so put them in a preserve whitespace
|
||||
# element with a single space.
|
||||
if not preserve_whitespace and len(r) and r[-1].text and r[-1].text.endswith(' '):
|
||||
r[-1].text = r[-1].text.rstrip()
|
||||
add_text(' ', True)
|
||||
makeelement(r, 'w:softHyphen')
|
||||
elif x:
|
||||
if not preserve_whitespace and x.startswith(' ') and len(r) and r[-1].tag and 'softHyphen' in r[-1].tag:
|
||||
x = x.lstrip()
|
||||
add_text(' ', True)
|
||||
add_text(x, preserve_whitespace)
|
||||
else:
|
||||
add_text('', preserve_whitespace)
|
||||
add_text('', preserve_whitespace)
|
||||
if bookmark is not None:
|
||||
makeelement(r, 'w:bookmarkEnd', w_id=str(bid))
|
||||
|
||||
@@ -537,15 +536,14 @@ class Convert:
|
||||
elif display in {'table', 'inline-table'}:
|
||||
self.blocks.end_current_block()
|
||||
self.blocks.start_new_table(html_tag, tag_style)
|
||||
elif tagname == 'img' and is_float:
|
||||
# Image is floating so don't start a new paragraph for it
|
||||
self.add_inline_tag(tagname, html_tag, tag_style, stylizer)
|
||||
else:
|
||||
if tagname == 'img' and is_float:
|
||||
# Image is floating so don't start a new paragraph for it
|
||||
self.add_inline_tag(tagname, html_tag, tag_style, stylizer)
|
||||
else:
|
||||
if tagname == 'hr':
|
||||
for edge in 'right bottom left'.split():
|
||||
tag_style.set(f'border-{edge}-style', 'none')
|
||||
self.add_block_tag(tagname, html_tag, tag_style, stylizer, float_spec=float_spec)
|
||||
if tagname == 'hr':
|
||||
for edge in 'right bottom left'.split():
|
||||
tag_style.set(f'border-{edge}-style', 'none')
|
||||
self.add_block_tag(tagname, html_tag, tag_style, stylizer, float_spec=float_spec)
|
||||
|
||||
for child in html_tag.iterchildren():
|
||||
if isinstance(getattr(child, 'tag', None), string_or_bytes):
|
||||
@@ -614,13 +612,12 @@ class Convert:
|
||||
elif tagname == 'img':
|
||||
block = self.create_block_from_parent(html_tag, stylizer)
|
||||
self.images_manager.add_image(html_tag, block, stylizer, bookmark=bmark)
|
||||
else:
|
||||
if html_tag.text:
|
||||
block = self.create_block_from_parent(html_tag, stylizer)
|
||||
block.add_text(html_tag.text, tag_style, is_parent_style=False, bookmark=bmark, link=self.current_link, lang=self.current_lang)
|
||||
elif bmark:
|
||||
block = self.create_block_from_parent(html_tag, stylizer)
|
||||
block.add_text('', tag_style, is_parent_style=False, bookmark=bmark, link=self.current_link, lang=self.current_lang)
|
||||
elif html_tag.text:
|
||||
block = self.create_block_from_parent(html_tag, stylizer)
|
||||
block.add_text(html_tag.text, tag_style, is_parent_style=False, bookmark=bmark, link=self.current_link, lang=self.current_lang)
|
||||
elif bmark:
|
||||
block = self.create_block_from_parent(html_tag, stylizer)
|
||||
block.add_text('', tag_style, is_parent_style=False, bookmark=bmark, link=self.current_link, lang=self.current_lang)
|
||||
|
||||
def bookmark_for_anchor(self, anchor, html_tag):
|
||||
return self.links_manager.bookmark_for_anchor(anchor, self.current_item, html_tag)
|
||||
|
||||
@@ -629,19 +629,17 @@ class BlockStyle(DOCXStyle):
|
||||
if css_val >= 0:
|
||||
if (self is normal_style and chars > 0) or self.css_text_indent != normal_style.css_text_indent:
|
||||
ind.set(w('firstLineChars'), str(chars))
|
||||
else:
|
||||
if (self is normal_style and chars < 0) or self.css_text_indent != normal_style.css_text_indent:
|
||||
ind.set(w('hangingChars'), str(abs(chars)))
|
||||
elif (self is normal_style and chars < 0) or self.css_text_indent != normal_style.css_text_indent:
|
||||
ind.set(w('hangingChars'), str(abs(chars)))
|
||||
else:
|
||||
val = self.text_indent
|
||||
if val >= 0:
|
||||
if (self is normal_style and val > 0) or self.text_indent != normal_style.text_indent:
|
||||
ind.set(w('firstLine'), str(val))
|
||||
ind.set(w('firstLineChars'), '0') # This is needed to override any declaration in the parent style
|
||||
else:
|
||||
if (self is normal_style and val < 0) or self.text_indent != normal_style.text_indent:
|
||||
ind.set(w('hanging'), str(abs(val)))
|
||||
ind.set(w('hangingChars'), '0')
|
||||
elif (self is normal_style and val < 0) or self.text_indent != normal_style.text_indent:
|
||||
ind.set(w('hanging'), str(abs(val)))
|
||||
ind.set(w('hangingChars'), '0')
|
||||
if ind.attrib:
|
||||
pPr.append(ind)
|
||||
|
||||
|
||||
@@ -324,12 +324,11 @@ class Table:
|
||||
if tcell is None:
|
||||
nrow.cells.extend([SpannedCell(nrow.cells[-1], horizontal=True) for i in range(idx - len(nrow.cells))])
|
||||
nrow.cells.append(sc)
|
||||
elif isinstance(tcell, SpannedCell):
|
||||
# Conflict between rowspan and colspan
|
||||
break
|
||||
else:
|
||||
if isinstance(tcell, SpannedCell):
|
||||
# Conflict between rowspan and colspan
|
||||
break
|
||||
else:
|
||||
nrow.cells.insert(idx, sc)
|
||||
nrow.cells.insert(idx, sc)
|
||||
|
||||
def start_new_row(self, html_tag, html_style):
|
||||
if self.current_row is not None:
|
||||
|
||||
@@ -218,9 +218,8 @@ def remove_attrs(attrs, tag):
|
||||
if a == '*':
|
||||
changed = True
|
||||
tag.attrib.clear()
|
||||
else:
|
||||
if tag.attrib.pop(a, None) is not None:
|
||||
changed = True
|
||||
elif tag.attrib.pop(a, None) is not None:
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
|
||||
|
||||
@@ -432,11 +432,10 @@ class HTMLConverter:
|
||||
pdict[key][pseudo] = val
|
||||
else:
|
||||
pdict[key] = {pseudo:val}
|
||||
elif key in sdict:
|
||||
sdict[key].update(val)
|
||||
else:
|
||||
if key in sdict:
|
||||
sdict[key].update(val)
|
||||
else:
|
||||
sdict[key] = val
|
||||
sdict[key] = val
|
||||
return sdict, pdict
|
||||
|
||||
def parse_style_properties(self, props):
|
||||
@@ -1202,27 +1201,26 @@ class HTMLConverter:
|
||||
ans = int(font_size('smaller'))
|
||||
if ans < 0:
|
||||
ans = normal
|
||||
else:
|
||||
if ans == 0:
|
||||
ans = int(font_size('smaller'))
|
||||
elif 'smaller' in val:
|
||||
ans = normal - 20
|
||||
elif 'xx-small' in val:
|
||||
ans = 40
|
||||
elif 'x-small' in val:
|
||||
ans = 60
|
||||
elif 'small' in val:
|
||||
ans = 80
|
||||
elif 'medium' in val:
|
||||
ans = 100
|
||||
elif 'larger' in val:
|
||||
ans = normal + 20
|
||||
elif 'xx-large' in val:
|
||||
ans = 180
|
||||
elif 'x-large' in val:
|
||||
ans = 140
|
||||
elif 'large' in val:
|
||||
ans = 120
|
||||
elif ans == 0:
|
||||
ans = int(font_size('smaller'))
|
||||
elif 'smaller' in val:
|
||||
ans = normal - 20
|
||||
elif 'xx-small' in val:
|
||||
ans = 40
|
||||
elif 'x-small' in val:
|
||||
ans = 60
|
||||
elif 'small' in val:
|
||||
ans = 80
|
||||
elif 'medium' in val:
|
||||
ans = 100
|
||||
elif 'larger' in val:
|
||||
ans = normal + 20
|
||||
elif 'xx-large' in val:
|
||||
ans = 180
|
||||
elif 'x-large' in val:
|
||||
ans = 140
|
||||
elif 'large' in val:
|
||||
ans = 120
|
||||
if ans is not None:
|
||||
ans += int(self.font_delta * 20)
|
||||
ans = str(ans)
|
||||
|
||||
@@ -899,15 +899,14 @@ class Text(LRFStream):
|
||||
elif c is None:
|
||||
p = open_containers.pop()
|
||||
s += p.close_html()
|
||||
elif c.name == 'P':
|
||||
in_p = True
|
||||
elif c.name == 'CR':
|
||||
s += '<br />' if in_p else '<p>'
|
||||
else:
|
||||
if c.name == 'P':
|
||||
in_p = True
|
||||
elif c.name == 'CR':
|
||||
s += '<br />' if in_p else '<p>'
|
||||
else:
|
||||
s += c.to_html()
|
||||
if not c.self_closing:
|
||||
open_containers.append(c)
|
||||
s += c.to_html()
|
||||
if not c.self_closing:
|
||||
open_containers.append(c)
|
||||
|
||||
if len(open_containers) > 0:
|
||||
raise LRFParseError(f'Malformed text stream {[i.name for i in open_containers if isinstance(i, Text.TextTag)]}')
|
||||
|
||||
@@ -405,13 +405,12 @@ class LrfTag:
|
||||
writeString(lrf, struct.pack(f, *p))
|
||||
else:
|
||||
writeString(lrf, struct.pack(f, p))
|
||||
elif f in [writeUnicode, writeRaw, writeEmpDots]:
|
||||
if encoding is None:
|
||||
raise LrfError('Tag requires encoding')
|
||||
f(lrf, p, encoding)
|
||||
else:
|
||||
if f in [writeUnicode, writeRaw, writeEmpDots]:
|
||||
if encoding is None:
|
||||
raise LrfError('Tag requires encoding')
|
||||
f(lrf, p, encoding)
|
||||
else:
|
||||
f(lrf, p)
|
||||
f(lrf, p)
|
||||
|
||||
|
||||
STREAM_SCRAMBLED = 0x200
|
||||
|
||||
@@ -139,11 +139,10 @@ def appendTextElements(e, contentsList, se):
|
||||
lastElement = newElement
|
||||
lastElement.tail = ''
|
||||
e.append(lastElement)
|
||||
elif lastElement is None:
|
||||
e.text = uconcat(e.text, content.text, se)
|
||||
else:
|
||||
if lastElement is None:
|
||||
e.text = uconcat(e.text, content.text, se)
|
||||
else:
|
||||
lastElement.tail = uconcat(lastElement.tail, content.text, se)
|
||||
lastElement.tail = uconcat(lastElement.tail, content.text, se)
|
||||
|
||||
|
||||
class Delegator:
|
||||
@@ -178,10 +177,9 @@ class Delegator:
|
||||
for d in self.delegates:
|
||||
if hasattr(d, 'applySetting'):
|
||||
applied = applied or d.applySetting(name, value)
|
||||
else:
|
||||
if name in d.getSettings():
|
||||
setattr(d, name, value)
|
||||
applied = True
|
||||
elif name in d.getSettings():
|
||||
setattr(d, name, value)
|
||||
applied = True
|
||||
|
||||
if testValid and not applied:
|
||||
raise LrsError(f'setting {name} not valid')
|
||||
|
||||
@@ -40,9 +40,8 @@ def get_document_info(stream):
|
||||
found = True
|
||||
pos = stream.tell() - actual_block_size + idx - len(prefix)
|
||||
stream.seek(pos)
|
||||
else:
|
||||
if block.find(br'\sect') > -1:
|
||||
break
|
||||
elif block.find(br'\sect') > -1:
|
||||
break
|
||||
if not found:
|
||||
return None, 0
|
||||
data, count, = [], 0
|
||||
|
||||
@@ -122,14 +122,13 @@ class ISBNMerge:
|
||||
if xw.is_alive():
|
||||
self.log.error('Query to xISBN timed out')
|
||||
self.use_xisbn = False
|
||||
elif xw.exception:
|
||||
self.log.error('Query to xISBN failed:')
|
||||
self.log.debug(xw.tb)
|
||||
else:
|
||||
if xw.exception:
|
||||
self.log.error('Query to xISBN failed:')
|
||||
self.log.debug(xw.tb)
|
||||
else:
|
||||
isbns, min_year = xw.isbns, xw.min_year
|
||||
if not msprefs['find_first_edition_date']:
|
||||
min_year = None
|
||||
isbns, min_year = xw.isbns, xw.min_year
|
||||
if not msprefs['find_first_edition_date']:
|
||||
min_year = None
|
||||
if not isbns:
|
||||
isbns = frozenset([isbn])
|
||||
if isbns in self.pools:
|
||||
|
||||
@@ -189,11 +189,10 @@ class MetadataUpdater:
|
||||
return pack('>BB',ans[1],ans[0]).decode('iso-8859-1')
|
||||
else:
|
||||
return pack('>B', b).decode('iso-8859-1')
|
||||
elif ans:
|
||||
ans.append(b|0x80)
|
||||
else:
|
||||
if ans:
|
||||
ans.append(b|0x80)
|
||||
else:
|
||||
ans.append(b)
|
||||
ans.append(b)
|
||||
|
||||
# If value == 0, return 0
|
||||
return pack('>B', 0x0).decode('iso-8859-1')
|
||||
|
||||
@@ -452,17 +452,16 @@ class MobiReader:
|
||||
pass
|
||||
elif tag.tag == 'img':
|
||||
tag.set('height', height)
|
||||
else:
|
||||
if tag.tag == 'div' and not tag.text and \
|
||||
elif tag.tag == 'div' and not tag.text and \
|
||||
(not tag.tail or not tag.tail.strip()) and \
|
||||
not list(tag.iterdescendants()):
|
||||
# Paragraph spacer
|
||||
# Insert nbsp so that the element is never
|
||||
# discarded by a renderer
|
||||
tag.text = '\u00a0' # nbsp
|
||||
styles.append(f'height: {self.ensure_unit(height)}')
|
||||
else:
|
||||
styles.append(f'margin-top: {self.ensure_unit(height)}')
|
||||
# Paragraph spacer
|
||||
# Insert nbsp so that the element is never
|
||||
# discarded by a renderer
|
||||
tag.text = '\u00a0' # nbsp
|
||||
styles.append(f'height: {self.ensure_unit(height)}')
|
||||
else:
|
||||
styles.append(f'margin-top: {self.ensure_unit(height)}')
|
||||
if 'width' in attrib:
|
||||
width = attrib.pop('width').strip()
|
||||
if width and re.search(r'\d+', width):
|
||||
|
||||
@@ -274,20 +274,19 @@ class Mobi8Reader:
|
||||
format = 'file'
|
||||
dir = 'images'
|
||||
fname = 'svgimg' + nstr + '.svg'
|
||||
# search for CDATA and if exists inline it
|
||||
elif flowpart.find(b'[CDATA[') >= 0:
|
||||
typ = 'css'
|
||||
flowpart = b'<style type="text/css">\n' + flowpart + b'\n</style>\n'
|
||||
format = 'inline'
|
||||
dir = None
|
||||
fname = None
|
||||
else:
|
||||
# search for CDATA and if exists inline it
|
||||
if flowpart.find(b'[CDATA[') >= 0:
|
||||
typ = 'css'
|
||||
flowpart = b'<style type="text/css">\n' + flowpart + b'\n</style>\n'
|
||||
format = 'inline'
|
||||
dir = None
|
||||
fname = None
|
||||
else:
|
||||
# css - assume as standalone css file
|
||||
typ = 'css'
|
||||
format = 'file'
|
||||
dir = 'styles'
|
||||
fname = nstr + '.css'
|
||||
# css - assume as standalone css file
|
||||
typ = 'css'
|
||||
format = 'file'
|
||||
dir = 'styles'
|
||||
fname = nstr + '.css'
|
||||
|
||||
self.flows[j] = flowpart
|
||||
self.flowinfo.append(FlowInfo(typ, format, dir, fname))
|
||||
|
||||
@@ -283,11 +283,10 @@ class TBS: # {{{
|
||||
for l in itervalues(depth_map):
|
||||
l.sort(key=lambda x:x.offset)
|
||||
self.periodical_tbs(data, first, depth_map)
|
||||
elif not data:
|
||||
self.bytestring = b''
|
||||
else:
|
||||
if not data:
|
||||
self.bytestring = b''
|
||||
else:
|
||||
self.book_tbs(data, first)
|
||||
self.book_tbs(data, first)
|
||||
|
||||
def periodical_tbs(self, data, first, depth_map):
|
||||
buf = io.BytesIO()
|
||||
@@ -316,26 +315,25 @@ class TBS: # {{{
|
||||
else:
|
||||
parent_section_index = max(iter(self.section_map))
|
||||
|
||||
else:
|
||||
# Non terminal record
|
||||
# Non terminal record
|
||||
|
||||
if spanner is not None:
|
||||
# record is spanned by a single article
|
||||
parent_section_index = spanner.parent_index
|
||||
typ = (self.type_110 if parent_section_index == 1 else
|
||||
self.type_010)
|
||||
elif not depth_map[1]:
|
||||
# has only article nodes, i.e. spanned by a section
|
||||
elif spanner is not None:
|
||||
# record is spanned by a single article
|
||||
parent_section_index = spanner.parent_index
|
||||
typ = (self.type_110 if parent_section_index == 1 else
|
||||
self.type_010)
|
||||
elif not depth_map[1]:
|
||||
# has only article nodes, i.e. spanned by a section
|
||||
parent_section_index = depth_map[2][0].parent_index
|
||||
typ = (self.type_111 if parent_section_index == 1 else
|
||||
self.type_010)
|
||||
else:
|
||||
# has section transitions
|
||||
if depth_map[2]:
|
||||
parent_section_index = depth_map[2][0].parent_index
|
||||
typ = (self.type_111 if parent_section_index == 1 else
|
||||
self.type_010)
|
||||
else:
|
||||
# has section transitions
|
||||
if depth_map[2]:
|
||||
parent_section_index = depth_map[2][0].parent_index
|
||||
else:
|
||||
parent_section_index = depth_map[1][0].index
|
||||
typ = self.type_011
|
||||
parent_section_index = depth_map[1][0].index
|
||||
typ = self.type_011
|
||||
|
||||
buf.write(typ)
|
||||
|
||||
@@ -864,13 +862,12 @@ class Indexer: # {{{
|
||||
data['completes'].append(index)
|
||||
else:
|
||||
data['starts'].append(index)
|
||||
else:
|
||||
# Node starts before current records
|
||||
if index.next_offset <= next_offset:
|
||||
# Node ends in current record
|
||||
data['ends'].append(index)
|
||||
elif index.depth == deepest:
|
||||
data['spans'] = index
|
||||
# Node starts before current records
|
||||
elif index.next_offset <= next_offset:
|
||||
# Node ends in current record
|
||||
data['ends'].append(index)
|
||||
elif index.depth == deepest:
|
||||
data['spans'] = index
|
||||
|
||||
if (data['ends'] or data['completes'] or data['starts'] or
|
||||
data['spans'] is not None):
|
||||
|
||||
@@ -138,9 +138,8 @@ def as_string_type(pat, for_unicode):
|
||||
if for_unicode:
|
||||
if isinstance(pat, bytes):
|
||||
pat = pat.decode('utf-8')
|
||||
else:
|
||||
if isinstance(pat, str):
|
||||
pat = pat.encode('utf-8')
|
||||
elif isinstance(pat, str):
|
||||
pat = pat.encode('utf-8')
|
||||
return pat
|
||||
|
||||
|
||||
@@ -1545,9 +1544,8 @@ class TOC:
|
||||
if child is node:
|
||||
self.nodes.remove(child)
|
||||
return True
|
||||
else:
|
||||
if child.remove(node):
|
||||
return True
|
||||
elif child.remove(node):
|
||||
return True
|
||||
return False
|
||||
|
||||
def iter(self):
|
||||
|
||||
@@ -131,9 +131,8 @@ def normalize_font(cssvalue, font_family_as_list=False):
|
||||
if font_family_as_list:
|
||||
if isinstance(ans['font-family'], string_or_bytes):
|
||||
ans['font-family'] = [x.strip() for x in ans['font-family'].split(',')]
|
||||
else:
|
||||
if not isinstance(ans['font-family'], string_or_bytes):
|
||||
ans['font-family'] = serialize_font_family(ans['font-family'])
|
||||
elif not isinstance(ans['font-family'], string_or_bytes):
|
||||
ans['font-family'] = serialize_font_family(ans['font-family'])
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
@@ -733,11 +733,10 @@ class Container(ContainerBase): # {{{
|
||||
item.set('properties', ' '.join(props))
|
||||
else:
|
||||
del item.attrib['properties']
|
||||
else:
|
||||
if name == iname:
|
||||
added_names.append(iname)
|
||||
props.append(prop)
|
||||
item.set('properties', ' '.join(props))
|
||||
elif name == iname:
|
||||
added_names.append(iname)
|
||||
props.append(prop)
|
||||
item.set('properties', ' '.join(props))
|
||||
self.dirty(self.opf_name)
|
||||
return removed_names, added_names
|
||||
|
||||
@@ -1059,16 +1058,15 @@ class Container(ContainerBase): # {{{
|
||||
base = os.path.dirname(path)
|
||||
if not os.path.exists(base):
|
||||
os.makedirs(base)
|
||||
else:
|
||||
if self.cloned and allow_modification and os.path.exists(path) and nlinks_file(path) > 1:
|
||||
# Decouple this file from its links
|
||||
temp = path + 'xxx'
|
||||
shutil.copyfile(path, temp)
|
||||
if iswindows:
|
||||
retry_on_fail(os.unlink, path)
|
||||
else:
|
||||
os.unlink(path)
|
||||
os.rename(temp, path)
|
||||
elif self.cloned and allow_modification and os.path.exists(path) and nlinks_file(path) > 1:
|
||||
# Decouple this file from its links
|
||||
temp = path + 'xxx'
|
||||
shutil.copyfile(path, temp)
|
||||
if iswindows:
|
||||
retry_on_fail(os.unlink, path)
|
||||
else:
|
||||
os.unlink(path)
|
||||
os.rename(temp, path)
|
||||
return path
|
||||
|
||||
def open(self, name, mode='rb'):
|
||||
@@ -1146,11 +1144,10 @@ class EpubContainer(Container):
|
||||
try:
|
||||
if v.major == 2:
|
||||
ans += ' 2'
|
||||
elif not v.minor:
|
||||
ans += f' {v.major}'
|
||||
else:
|
||||
if not v.minor:
|
||||
ans += f' {v.major}'
|
||||
else:
|
||||
ans += f' {v.major}.{v.minor}'
|
||||
ans += f' {v.major}.{v.minor}'
|
||||
except Exception:
|
||||
pass
|
||||
return ans
|
||||
|
||||
@@ -23,11 +23,10 @@ def set_azw3_cover(container, cover_path, report, options=None):
|
||||
if existing_image:
|
||||
name = cover_path
|
||||
found = False
|
||||
else:
|
||||
if name is None or not container.has_name(name):
|
||||
item = container.generate_item(name='cover.jpeg', id_prefix='cover')
|
||||
name = container.href_to_name(item.get('href'), container.opf_name)
|
||||
found = False
|
||||
elif name is None or not container.has_name(name):
|
||||
item = container.generate_item(name='cover.jpeg', id_prefix='cover')
|
||||
name = container.href_to_name(item.get('href'), container.opf_name)
|
||||
found = False
|
||||
href = container.name_to_href(name, container.opf_name)
|
||||
guide = container.opf_xpath('//opf:guide')[0]
|
||||
container.insert_into_xml(guide, guide.makeelement(
|
||||
@@ -365,26 +364,25 @@ def create_epub_cover(container, cover_path, existing_image, options=None):
|
||||
style = 'style="height: 100%%"'
|
||||
templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style)
|
||||
has_svg = False
|
||||
elif callable(cover_path):
|
||||
templ = (options or {}).get('template', CoverManager.SVG_TEMPLATE)
|
||||
has_svg = 'xlink:href' in templ
|
||||
else:
|
||||
if callable(cover_path):
|
||||
templ = (options or {}).get('template', CoverManager.SVG_TEMPLATE)
|
||||
has_svg = 'xlink:href' in templ
|
||||
else:
|
||||
width, height = 600, 800
|
||||
has_svg = True
|
||||
try:
|
||||
if existing_image:
|
||||
width, height = identify(container.raw_data(existing_image, decode=False))[1:]
|
||||
else:
|
||||
with open(cover_path, 'rb') as csrc:
|
||||
width, height = identify(csrc)[1:]
|
||||
except Exception:
|
||||
container.log.exception('Failed to get width and height of cover')
|
||||
ar = 'xMidYMid meet' if keep_aspect else 'none'
|
||||
templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar)
|
||||
templ = templ.replace('__viewbox__', f'0 0 {width} {height}')
|
||||
templ = templ.replace('__width__', str(width))
|
||||
templ = templ.replace('__height__', str(height))
|
||||
width, height = 600, 800
|
||||
has_svg = True
|
||||
try:
|
||||
if existing_image:
|
||||
width, height = identify(container.raw_data(existing_image, decode=False))[1:]
|
||||
else:
|
||||
with open(cover_path, 'rb') as csrc:
|
||||
width, height = identify(csrc)[1:]
|
||||
except Exception:
|
||||
container.log.exception('Failed to get width and height of cover')
|
||||
ar = 'xMidYMid meet' if keep_aspect else 'none'
|
||||
templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar)
|
||||
templ = templ.replace('__viewbox__', f'0 0 {width} {height}')
|
||||
templ = templ.replace('__width__', str(width))
|
||||
templ = templ.replace('__height__', str(height))
|
||||
folder = recommended_folders[tname]
|
||||
if folder:
|
||||
tname = folder + '/' + tname
|
||||
|
||||
@@ -50,11 +50,10 @@ def find_existing_jacket(container):
|
||||
root = container.parsed(name)
|
||||
if is_current_jacket(root):
|
||||
return name
|
||||
else:
|
||||
if name.rpartition('/')[-1].startswith('jacket') and name.endswith('.xhtml'):
|
||||
root = container.parsed(name)
|
||||
if is_current_jacket(root) or is_legacy_jacket(root):
|
||||
return name
|
||||
elif name.rpartition('/')[-1].startswith('jacket') and name.endswith('.xhtml'):
|
||||
root = container.parsed(name)
|
||||
if is_current_jacket(root) or is_legacy_jacket(root):
|
||||
return name
|
||||
|
||||
|
||||
def replace_jacket(container, name):
|
||||
|
||||
@@ -362,11 +362,10 @@ def remove_links_to(container, predicate):
|
||||
if predicate(hname, href, frag):
|
||||
if attr is None:
|
||||
el.text = None
|
||||
elif el.tag == XHTML('link') or el.tag == XHTML('img'):
|
||||
extract(el)
|
||||
else:
|
||||
if el.tag == XHTML('link') or el.tag == XHTML('img'):
|
||||
extract(el)
|
||||
else:
|
||||
del el.attrib[attr]
|
||||
del el.attrib[attr]
|
||||
removed = True
|
||||
for tag in stylepath(root):
|
||||
if tag.text and (tag.get('type') or 'text/css').lower() == 'text/css':
|
||||
|
||||
@@ -184,19 +184,18 @@ def links_data(container, *args):
|
||||
for base, frag, dest, location, text in links:
|
||||
if dest is None:
|
||||
link = Link(location, text, True, base, True, True, Anchor(frag, None, None))
|
||||
else:
|
||||
if dest in anchor_map:
|
||||
loc = LinkLocation(dest, None, None)
|
||||
if frag:
|
||||
anchor = anchor_map[dest].get(frag)
|
||||
if anchor is None:
|
||||
link = Link(location, text, False, dest, True, False, Anchor(frag, loc, None))
|
||||
else:
|
||||
link = Link(location, text, False, dest, True, True, Anchor(frag, *anchor))
|
||||
elif dest in anchor_map:
|
||||
loc = LinkLocation(dest, None, None)
|
||||
if frag:
|
||||
anchor = anchor_map[dest].get(frag)
|
||||
if anchor is None:
|
||||
link = Link(location, text, False, dest, True, False, Anchor(frag, loc, None))
|
||||
else:
|
||||
link = Link(location, text, False, dest, True, True, Anchor(None, loc, None))
|
||||
link = Link(location, text, False, dest, True, True, Anchor(frag, *anchor))
|
||||
else:
|
||||
link = Link(location, text, False, dest, False, False, Anchor(frag, None, None))
|
||||
link = Link(location, text, False, dest, True, True, Anchor(None, loc, None))
|
||||
else:
|
||||
link = Link(location, text, False, dest, False, False, Anchor(frag, None, None))
|
||||
yield link
|
||||
|
||||
|
||||
|
||||
@@ -493,9 +493,8 @@ def embed_tts(container, report_progress=None, callback_to_download_voices=None)
|
||||
name_map.pop(rname)
|
||||
if callback_to_download_voices is None:
|
||||
piper.ensure_voices_downloaded(iter(all_voices))
|
||||
else:
|
||||
if not callback_to_download_voices(partial(piper.ensure_voices_downloaded, iter(all_voices))):
|
||||
return False
|
||||
elif not callback_to_download_voices(partial(piper.ensure_voices_downloaded, iter(all_voices))):
|
||||
return False
|
||||
stage = _('Converting text to speech')
|
||||
if report_progress(stage, '', 0, total_num_sentences):
|
||||
return False
|
||||
|
||||
@@ -358,13 +358,12 @@ class OEBReader:
|
||||
item = manifest.ids[idref]
|
||||
if item.media_type.lower() in OEB_DOCS and hasattr(item.data, 'xpath') and not getattr(item.data, 'tag', '').endswith('}ncx'):
|
||||
spine.add(item, elem.get('linear'))
|
||||
elif hasattr(item.data, 'tag') and item.data.tag and item.data.tag.endswith('}html'):
|
||||
item.media_type = XHTML_MIME
|
||||
spine.add(item, elem.get('linear'))
|
||||
else:
|
||||
if hasattr(item.data, 'tag') and item.data.tag and item.data.tag.endswith('}html'):
|
||||
item.media_type = XHTML_MIME
|
||||
spine.add(item, elem.get('linear'))
|
||||
else:
|
||||
self.oeb.log.warn(f'The item {item.href} is not a XML document.'
|
||||
' Removing it from spine.')
|
||||
self.oeb.log.warn(f'The item {item.href} is not a XML document.'
|
||||
' Removing it from spine.')
|
||||
if len(spine) == 0:
|
||||
raise OEBError('Spine is empty')
|
||||
self._spine_add_extra()
|
||||
|
||||
@@ -131,11 +131,10 @@ def parse_outline(raw, output_dir):
|
||||
if child.tag == 'outline':
|
||||
parent = toc.children[-1] if toc.children else toc
|
||||
process_node(child, parent)
|
||||
else:
|
||||
if child.text:
|
||||
page = child.get('page', '1')
|
||||
toc.add(child.text, 'index.html', 'p' + page)
|
||||
count[0] += 1
|
||||
elif child.text:
|
||||
page = child.get('page', '1')
|
||||
toc.add(child.text, 'index.html', 'p' + page)
|
||||
count[0] += 1
|
||||
process_node(outline, toc)
|
||||
if count[0] > 2:
|
||||
root = create_ncx(toc, (lambda x:x), 'pdftohtml', 'en', 'pdftohtml')
|
||||
|
||||
@@ -236,11 +236,10 @@ class Text(Element):
|
||||
and abs(other.left - self.right) < 2.0:
|
||||
# and abs(other.left - self.right) < self.average_character_width / 3.0:
|
||||
has_gap = 0
|
||||
else: # Insert n spaces to fill gap. Use TAB? Columns?
|
||||
if other.left < self.right:
|
||||
has_gap = 1 # Coalescing different lines. 1 space
|
||||
else: # Multiple texts on same line
|
||||
has_gap = round(0.5+abs(other.left - self.right) / self.average_character_width)
|
||||
elif other.left < self.right:
|
||||
has_gap = 1 # Coalescing different lines. 1 space
|
||||
else: # Multiple texts on same line
|
||||
has_gap = round(0.5+abs(other.left - self.right) / self.average_character_width)
|
||||
|
||||
# Allow for super or subscript. These probably have lower heights
|
||||
# In this case, don't use their top/bottom
|
||||
@@ -308,14 +307,13 @@ class Text(Element):
|
||||
has_gap = 1
|
||||
else:
|
||||
has_gap = 0
|
||||
else: # Large gap
|
||||
# Float right if the text ends around the right margin,
|
||||
# and there are no long groups of spaces earlier in the line
|
||||
# as that probably means justified text.
|
||||
if ' ' not in self.text_as_string \
|
||||
and other.right > right_margin - right_margin * RIGHT_FLOAT_FACTOR:
|
||||
has_float = '<span style="float:right">'
|
||||
has_gap = 1
|
||||
# Float right if the text ends around the right margin,
|
||||
# and there are no long groups of spaces earlier in the line
|
||||
# as that probably means justified text.
|
||||
elif ' ' not in self.text_as_string \
|
||||
and other.right > right_margin - right_margin * RIGHT_FLOAT_FACTOR:
|
||||
has_float = '<span style="float:right">'
|
||||
has_gap = 1
|
||||
# else leave has_gap
|
||||
old_float = re.match(r'^(.*)(<span style="float:right">.*)</span>\s*$', self.raw)
|
||||
if old_float:
|
||||
@@ -1064,24 +1062,23 @@ class Page:
|
||||
# Check for centred done later
|
||||
match = frag
|
||||
break # Leave tind
|
||||
else:
|
||||
# Check for start of a paragraph being indented
|
||||
# Ought to have some way of setting a standard indent
|
||||
if frag.tag == 'p':
|
||||
if frag.indented == 0 \
|
||||
and frag.align != 'C' \
|
||||
and frag.left > left_max + frag.average_character_width:
|
||||
# Is it approx self.stats_indent?
|
||||
if indent_min <= frag.left <= indent_max:
|
||||
frag.indented = 1 # 1em
|
||||
else: # Assume left margin of approx = number of chars
|
||||
# Should check for values approx the same, as with indents
|
||||
frag.margin_left = round(((frag.left - left_min) / self.stats_margin_px)+0.5)
|
||||
if last_frag is not None \
|
||||
and stats.para_space > 0 \
|
||||
and frag.bottom - last_frag.bottom > stats.para_space*SECTION_FACTOR:
|
||||
# and frag.top - last_frag.bottom > frag.height + stats.line_space + (stats.line_space*LINE_FACTOR):
|
||||
frag.blank_line_before = 1
|
||||
# Check for start of a paragraph being indented
|
||||
# Ought to have some way of setting a standard indent
|
||||
elif frag.tag == 'p':
|
||||
if frag.indented == 0 \
|
||||
and frag.align != 'C' \
|
||||
and frag.left > left_max + frag.average_character_width:
|
||||
# Is it approx self.stats_indent?
|
||||
if indent_min <= frag.left <= indent_max:
|
||||
frag.indented = 1 # 1em
|
||||
else: # Assume left margin of approx = number of chars
|
||||
# Should check for values approx the same, as with indents
|
||||
frag.margin_left = round(((frag.left - left_min) / self.stats_margin_px)+0.5)
|
||||
if last_frag is not None \
|
||||
and stats.para_space > 0 \
|
||||
and frag.bottom - last_frag.bottom > stats.para_space*SECTION_FACTOR:
|
||||
# and frag.top - last_frag.bottom > frag.height + stats.line_space + (stats.line_space*LINE_FACTOR):
|
||||
frag.blank_line_before = 1
|
||||
last_frag = frag
|
||||
tind += 1
|
||||
if match is not None:
|
||||
@@ -1802,26 +1799,25 @@ class PDFDocument:
|
||||
# t += ' ' + page.texts[1].text_as_string
|
||||
if len(head_text[head_ind]) == 0:
|
||||
head_text[head_ind] = t
|
||||
elif head_text[head_ind] == t:
|
||||
head_match[head_ind] += 1
|
||||
if head_page == 0:
|
||||
head_page = page.number
|
||||
elif re.match(pagenum_text, t) is not None:
|
||||
# Look for page count of format 'n xxx n'
|
||||
head_match1[head_ind] += 1
|
||||
if head_page == 0:
|
||||
head_page = page.number
|
||||
else:
|
||||
if head_text[head_ind] == t:
|
||||
head_match[head_ind] += 1
|
||||
if head_page == 0:
|
||||
head_page = page.number
|
||||
elif re.match(pagenum_text, t) is not None:
|
||||
# Look for page count of format 'n xxx n'
|
||||
head_match1[head_ind] += 1
|
||||
if head_page == 0:
|
||||
head_page = page.number
|
||||
else:
|
||||
# Look for text of format 'constant nn'
|
||||
f = re.match(fixed_text, t)
|
||||
if f and f.group(1):
|
||||
if not fixed_head:
|
||||
fixed_head = f.group(1)
|
||||
elif fixed_head == f.group(1):
|
||||
head_match2[head_ind] += 1
|
||||
if head_page == 0:
|
||||
head_page = page.number
|
||||
# Look for text of format 'constant nn'
|
||||
f = re.match(fixed_text, t)
|
||||
if f and f.group(1):
|
||||
if not fixed_head:
|
||||
fixed_head = f.group(1)
|
||||
elif fixed_head == f.group(1):
|
||||
head_match2[head_ind] += 1
|
||||
if head_page == 0:
|
||||
head_page = page.number
|
||||
|
||||
if self.opts.pdf_footer_skip < 0 \
|
||||
and len(page.texts) > 0:
|
||||
@@ -1835,26 +1831,25 @@ class PDFDocument:
|
||||
# t += ' ' + page.texts[-2].text_as_string
|
||||
if len(foot_text[foot_ind]) == 0:
|
||||
foot_text[foot_ind] = t
|
||||
elif foot_text[foot_ind] == t:
|
||||
foot_match[foot_ind] += 1
|
||||
if foot_page == 0:
|
||||
foot_page = page.number
|
||||
elif re.match(pagenum_text, t) is not None:
|
||||
# Look for page count of format 'n xxx n'
|
||||
foot_match1[foot_ind] += 1
|
||||
if foot_page == 0:
|
||||
foot_page = page.number
|
||||
else:
|
||||
if foot_text[foot_ind] == t:
|
||||
foot_match[foot_ind] += 1
|
||||
if foot_page == 0:
|
||||
foot_page = page.number
|
||||
elif re.match(pagenum_text, t) is not None:
|
||||
# Look for page count of format 'n xxx n'
|
||||
foot_match1[foot_ind] += 1
|
||||
if foot_page == 0:
|
||||
foot_page = page.number
|
||||
else:
|
||||
# Look for text of format 'constant nn'
|
||||
f = re.match(fixed_text, t)
|
||||
if f and f.group(1):
|
||||
if not fixed_foot:
|
||||
fixed_foot = f.group(1)
|
||||
elif fixed_foot == f.group(1):
|
||||
foot_match2[foot_ind] += 1
|
||||
if foot_page == 0:
|
||||
foot_page = page.number
|
||||
# Look for text of format 'constant nn'
|
||||
f = re.match(fixed_text, t)
|
||||
if f and f.group(1):
|
||||
if not fixed_foot:
|
||||
fixed_foot = f.group(1)
|
||||
elif fixed_foot == f.group(1):
|
||||
foot_match2[foot_ind] += 1
|
||||
if foot_page == 0:
|
||||
foot_page = page.number
|
||||
|
||||
pages_to_scan -= 1
|
||||
if pages_to_scan < 1:
|
||||
|
||||
@@ -426,10 +426,9 @@ class PDFStream:
|
||||
if fmt == QImage.Format.Format_MonoLSB:
|
||||
image = image.convertToFormat(QImage.Format.Format_Mono)
|
||||
fmt = QImage.Format.Format_Mono
|
||||
else:
|
||||
if (fmt != QImage.Format.Format_RGB32 and fmt != QImage.Format.Format_ARGB32):
|
||||
image = image.convertToFormat(QImage.Format.Format_ARGB32)
|
||||
fmt = QImage.Format.Format_ARGB32
|
||||
elif (fmt != QImage.Format.Format_RGB32 and fmt != QImage.Format.Format_ARGB32):
|
||||
image = image.convertToFormat(QImage.Format.Format_ARGB32)
|
||||
fmt = QImage.Format.Format_ARGB32
|
||||
|
||||
w = image.width()
|
||||
h = image.height()
|
||||
|
||||
@@ -314,16 +314,15 @@ class PML_HTMLizer:
|
||||
text = self.STATES_TAGS[code][1] % self.state[code][1]
|
||||
else:
|
||||
text = self.STATES_TAGS[code][1]
|
||||
else:
|
||||
if code in self.STATES_VALUE_REQ or code in self.STATES_VALUE_REQ_2:
|
||||
val = self.code_value(stream)
|
||||
if code in self.STATES_VALUE_REQ:
|
||||
text = self.STATES_TAGS[code][0] % val
|
||||
else:
|
||||
text = self.STATES_TAGS[code][0] % (val, val)
|
||||
self.state[code][1] = val
|
||||
elif code in self.STATES_VALUE_REQ or code in self.STATES_VALUE_REQ_2:
|
||||
val = self.code_value(stream)
|
||||
if code in self.STATES_VALUE_REQ:
|
||||
text = self.STATES_TAGS[code][0] % val
|
||||
else:
|
||||
text = self.STATES_TAGS[code][0]
|
||||
text = self.STATES_TAGS[code][0] % (val, val)
|
||||
self.state[code][1] = val
|
||||
else:
|
||||
text = self.STATES_TAGS[code][0]
|
||||
|
||||
return text
|
||||
|
||||
@@ -406,16 +405,15 @@ class PML_HTMLizer:
|
||||
else:
|
||||
text += self.STATES_TAGS[c][0]
|
||||
# Open code.
|
||||
else:
|
||||
if code in self.STATES_VALUE_REQ or code in self.STATES_VALUE_REQ_2:
|
||||
val = self.code_value(stream)
|
||||
if code in self.STATES_VALUE_REQ:
|
||||
text += self.STATES_TAGS[code][0] % val
|
||||
else:
|
||||
text += self.STATES_TAGS[code][0] % (val, val)
|
||||
self.state[code][1] = val
|
||||
elif code in self.STATES_VALUE_REQ or code in self.STATES_VALUE_REQ_2:
|
||||
val = self.code_value(stream)
|
||||
if code in self.STATES_VALUE_REQ:
|
||||
text += self.STATES_TAGS[code][0] % val
|
||||
else:
|
||||
text += self.STATES_TAGS[code][0]
|
||||
text += self.STATES_TAGS[code][0] % (val, val)
|
||||
self.state[code][1] = val
|
||||
else:
|
||||
text += self.STATES_TAGS[code][0]
|
||||
|
||||
return text
|
||||
|
||||
@@ -436,21 +434,20 @@ class PML_HTMLizer:
|
||||
text += self.STATES_TAGS[code][1] % self.state[code][1]
|
||||
else:
|
||||
text += self.STATES_TAGS[code][1]
|
||||
else:
|
||||
# Open tag
|
||||
if code in self.STATES_VALUE_REQ or code in self.STATES_VALUE_REQ_2:
|
||||
val = self.code_value(stream)
|
||||
if code in self.LINK_STATES:
|
||||
val = val.lstrip('#')
|
||||
if pre:
|
||||
val = f'{pre}-{val}'
|
||||
if code in self.STATES_VALUE_REQ:
|
||||
text += self.STATES_TAGS[code][0] % val
|
||||
else:
|
||||
text += self.STATES_TAGS[code][0] % (val, val)
|
||||
self.state[code][1] = val
|
||||
# Open tag
|
||||
elif code in self.STATES_VALUE_REQ or code in self.STATES_VALUE_REQ_2:
|
||||
val = self.code_value(stream)
|
||||
if code in self.LINK_STATES:
|
||||
val = val.lstrip('#')
|
||||
if pre:
|
||||
val = f'{pre}-{val}'
|
||||
if code in self.STATES_VALUE_REQ:
|
||||
text += self.STATES_TAGS[code][0] % val
|
||||
else:
|
||||
text += self.STATES_TAGS[code][0]
|
||||
text += self.STATES_TAGS[code][0] % (val, val)
|
||||
self.state[code][1] = val
|
||||
else:
|
||||
text += self.STATES_TAGS[code][0]
|
||||
|
||||
# Re-open all spans if code was a div based on state
|
||||
for c in self.SPAN_STATES:
|
||||
|
||||
@@ -375,11 +375,10 @@ class PMLMLizer:
|
||||
# a new text block.
|
||||
if tag == 'block':
|
||||
text.append('\n\n')
|
||||
# closing \c and \r need to be placed
|
||||
# on the next line per PML spec.
|
||||
elif tag in ('c', 'r'):
|
||||
text.append(f'\n\\{tag}')
|
||||
else:
|
||||
# closing \c and \r need to be placed
|
||||
# on the next line per PML spec.
|
||||
if tag in ('c', 'r'):
|
||||
text.append(f'\n\\{tag}')
|
||||
else:
|
||||
text.append(rf'\{tag}')
|
||||
text.append(rf'\{tag}')
|
||||
return text
|
||||
|
||||
@@ -133,18 +133,17 @@ class Document:
|
||||
best_candidate = self.select_best_candidate(candidates)
|
||||
if best_candidate:
|
||||
article = self.get_article(candidates, best_candidate)
|
||||
elif ruthless:
|
||||
self.log.debug('ruthless removal did not work. ')
|
||||
ruthless = False
|
||||
self.debug('ended up stripping too much - going for a safer _parse')
|
||||
# try again
|
||||
continue
|
||||
else:
|
||||
if ruthless:
|
||||
self.log.debug('ruthless removal did not work. ')
|
||||
ruthless = False
|
||||
self.debug('ended up stripping too much - going for a safer _parse')
|
||||
# try again
|
||||
continue
|
||||
else:
|
||||
self.log.debug('Ruthless and lenient parsing did not work. Returning raw html')
|
||||
article = self.html.find('body')
|
||||
if article is None:
|
||||
article = self.html
|
||||
self.log.debug('Ruthless and lenient parsing did not work. Returning raw html')
|
||||
article = self.html.find('body')
|
||||
if article is None:
|
||||
article = self.html
|
||||
|
||||
cleaned_article = self.sanitize(article, candidates)
|
||||
of_acceptable_length = len(cleaned_article or '') >= (self.options['retry_length'] or self.RETRY_LENGTH)
|
||||
|
||||
@@ -131,10 +131,9 @@ class Render(QWebEnginePage):
|
||||
if monotonic() - self.start_time > PRINT_TIMEOUT:
|
||||
self.hang_timer.stop()
|
||||
QApplication.instance().exit(4)
|
||||
else:
|
||||
if monotonic() - self.start_time > LOAD_TIMEOUT:
|
||||
self.hang_timer.stop()
|
||||
QApplication.instance().exit(3)
|
||||
elif monotonic() - self.start_time > LOAD_TIMEOUT:
|
||||
self.hang_timer.stop()
|
||||
QApplication.instance().exit(3)
|
||||
|
||||
def start_print(self, data):
|
||||
margins = QMarginsF(0, 0, 0, 0)
|
||||
|
||||
@@ -225,9 +225,8 @@ class AddBrackets:
|
||||
if self.__copy:
|
||||
copy_obj.copy_file(self.__write_to, 'add_brackets.data')
|
||||
copy_obj.rename(self.__write_to, self.__file)
|
||||
else:
|
||||
if self.__run_level > 0:
|
||||
sys.stderr.write(
|
||||
'Sorry, but this files has a mix of old and new RTF.\n'
|
||||
'Some characteristics cannot be converted.\n')
|
||||
elif self.__run_level > 0:
|
||||
sys.stderr.write(
|
||||
'Sorry, but this files has a mix of old and new RTF.\n'
|
||||
'Some characteristics cannot be converted.\n')
|
||||
os.remove(self.__write_to)
|
||||
|
||||
@@ -68,11 +68,10 @@ class BodyStyles:
|
||||
the_string = ''.join(self.__list_of_styles)
|
||||
self.__write_obj.write(the_string)
|
||||
self.__write_obj.write('mi<tg<close_____<styles-in-body\n')
|
||||
else:
|
||||
# this shouldn't happen!
|
||||
if self.__run_level > 3:
|
||||
msg = 'Not enough data for each table\n'
|
||||
raise self.__bug_handler(msg)
|
||||
# this shouldn't happen!
|
||||
elif self.__run_level > 3:
|
||||
msg = 'Not enough data for each table\n'
|
||||
raise self.__bug_handler(msg)
|
||||
# why was this line even here?
|
||||
# self.__write_obj.write('mi<tg<open______<table\n')
|
||||
self.__write_obj.write(line)
|
||||
|
||||
@@ -184,7 +184,6 @@ class BorderParse:
|
||||
new_border_dict[att] = 'hairline'
|
||||
elif 'single' in border_style_list:
|
||||
new_border_dict[att] = 'single'
|
||||
else:
|
||||
if border_style_list:
|
||||
new_border_dict[att] = border_style_list[0]
|
||||
elif border_style_list:
|
||||
new_border_dict[att] = border_style_list[0]
|
||||
return new_border_dict
|
||||
|
||||
@@ -107,12 +107,11 @@ class Configure:
|
||||
configuration_dir = return_dict.get('configuration-directory')
|
||||
if configuration_dir is None:
|
||||
return_dict['configure-directory'] = None
|
||||
elif not os.path.isdir(configuration_dir):
|
||||
sys.stderr.write(f'The directory "{configuration_dir}" does not appear to be a directory.\n')
|
||||
return 1
|
||||
else:
|
||||
if not os.path.isdir(configuration_dir):
|
||||
sys.stderr.write(f'The directory "{configuration_dir}" does not appear to be a directory.\n')
|
||||
return 1
|
||||
else:
|
||||
return_dict['configure-directory'] = configuration_dir
|
||||
return_dict['configure-directory'] = configuration_dir
|
||||
smart_output = return_dict.get('smart-output')
|
||||
if not smart_output:
|
||||
return_dict['smart-output'] = 0
|
||||
|
||||
@@ -225,9 +225,8 @@ file.
|
||||
if in_see:
|
||||
if bracket_count == end_bracket_count and token_info == 'cb<nu<clos-brack':
|
||||
in_see = 0
|
||||
else:
|
||||
if token_info == 'tx<nu<__________':
|
||||
see_string += line[17:]
|
||||
elif token_info == 'tx<nu<__________':
|
||||
see_string += line[17:]
|
||||
else:
|
||||
if token_info == 'cw<in<index-see_':
|
||||
end_bracket_count = bracket_count - 1
|
||||
@@ -260,11 +259,10 @@ file.
|
||||
if bracket_count == end_bracket_count and token_info == 'cb<nu<clos-brack':
|
||||
in_bookmark = 0
|
||||
index_string += f'{line}\n'
|
||||
elif token_info == 'tx<nu<__________':
|
||||
bookmark_string += line[17:]
|
||||
else:
|
||||
if token_info == 'tx<nu<__________':
|
||||
bookmark_string += line[17:]
|
||||
else:
|
||||
index_string += f'{line}\n'
|
||||
index_string += f'{line}\n'
|
||||
else:
|
||||
if token_info == 'cw<an<place_____':
|
||||
end_bracket_count = bracket_count - 1
|
||||
@@ -347,14 +345,13 @@ file.
|
||||
if bracket_count == end_bracket_count and token_info == 'cb<nu<clos-brack':
|
||||
in_bookmark = 0
|
||||
toc_string += f'{line}\n'
|
||||
elif token_info == 'tx<nu<__________':
|
||||
if book_type == 'start':
|
||||
book_start_string += line[17:]
|
||||
elif book_type == 'end':
|
||||
book_end_string += line[17:]
|
||||
else:
|
||||
if token_info == 'tx<nu<__________':
|
||||
if book_type == 'start':
|
||||
book_start_string += line[17:]
|
||||
elif book_type == 'end':
|
||||
book_end_string += line[17:]
|
||||
else:
|
||||
toc_string += f'{line}\n'
|
||||
toc_string += f'{line}\n'
|
||||
else:
|
||||
if token_info == 'cw<an<book-mk-st' or token_info =='cw<an<book-mk-en':
|
||||
if token_info == 'cw<an<book-mk-st':
|
||||
|
||||
@@ -215,9 +215,8 @@ class Footnote:
|
||||
if line == 'mi<mk<footnt-clo\n':
|
||||
return string_to_return
|
||||
string_to_return = string_to_return + line
|
||||
else:
|
||||
if line == look_for:
|
||||
found_foot = 1
|
||||
elif line == look_for:
|
||||
found_foot = 1
|
||||
|
||||
def __join_from_temp(self):
|
||||
'''
|
||||
|
||||
@@ -215,9 +215,8 @@ class Header:
|
||||
if line == 'mi<mk<header-clo\n':
|
||||
return string_to_return
|
||||
string_to_return += line
|
||||
else:
|
||||
if line == look_for:
|
||||
found_head = True
|
||||
elif line == look_for:
|
||||
found_head = True
|
||||
|
||||
def __join_from_temp(self):
|
||||
'''
|
||||
|
||||
@@ -132,11 +132,10 @@ class Inline:
|
||||
self.__place = 'not_in_list'
|
||||
self.__inline_list = self.__body_inline_list
|
||||
self.__groups_in_waiting = self.__groups_in_waiting_body
|
||||
else:
|
||||
if self.__token_info == 'mi<mk<lst-tx-beg':
|
||||
self.__place = 'in_list'
|
||||
self.__inline_list = self.__list_inline_list
|
||||
self.__groups_in_waiting = self.__groups_in_waiting_list
|
||||
elif self.__token_info == 'mi<mk<lst-tx-beg':
|
||||
self.__place = 'in_list'
|
||||
self.__inline_list = self.__list_inline_list
|
||||
self.__groups_in_waiting = self.__groups_in_waiting_list
|
||||
|
||||
def __default_func(self, line):
|
||||
'''
|
||||
@@ -243,15 +242,14 @@ class Inline:
|
||||
self.__write_obj.write('mi<mk<font-end__\n')
|
||||
if 'caps' in the_keys:
|
||||
self.__write_obj.write('mi<mk<caps-end__\n')
|
||||
else:
|
||||
# close out only if in a paragraph
|
||||
if 'contains_inline' in the_keys and the_dict['contains_inline'] == 1\
|
||||
and self.__in_para and self.__groups_in_waiting[0] == 0:
|
||||
self.__write_obj.write('mi<tg<close_____<inline\n')
|
||||
if 'font-style' in the_keys:
|
||||
self.__write_obj.write('mi<mk<font-end__\n')
|
||||
if 'caps' in the_keys:
|
||||
self.__write_obj.write('mi<mk<caps-end__\n')
|
||||
# close out only if in a paragraph
|
||||
elif 'contains_inline' in the_keys and the_dict['contains_inline'] == 1\
|
||||
and self.__in_para and self.__groups_in_waiting[0] == 0:
|
||||
self.__write_obj.write('mi<tg<close_____<inline\n')
|
||||
if 'font-style' in the_keys:
|
||||
self.__write_obj.write('mi<mk<font-end__\n')
|
||||
if 'caps' in the_keys:
|
||||
self.__write_obj.write('mi<mk<caps-end__\n')
|
||||
self.__inline_list.pop()
|
||||
if self.__groups_in_waiting[0] != 0:
|
||||
self.__groups_in_waiting[0] -= 1
|
||||
@@ -272,12 +270,11 @@ class Inline:
|
||||
'''
|
||||
if self.__place == 'in_list':
|
||||
self.__write_inline()
|
||||
else:
|
||||
if not self.__in_para:
|
||||
self.__in_para = 1
|
||||
self.__start_para_func(line)
|
||||
elif self.__groups_in_waiting[0] != 0:
|
||||
self.__write_inline()
|
||||
elif not self.__in_para:
|
||||
self.__in_para = 1
|
||||
self.__start_para_func(line)
|
||||
elif self.__groups_in_waiting[0] != 0:
|
||||
self.__write_inline()
|
||||
|
||||
def __write_inline(self):
|
||||
'''
|
||||
|
||||
@@ -337,11 +337,10 @@ class ListTable:
|
||||
elif self.__token_info == 'cw<ls<list-name_':
|
||||
self.__state = 'list_name'
|
||||
self.__list_name_ob_count = self.__ob_count
|
||||
else:
|
||||
if self.__run_level > 3:
|
||||
msg = 'No matching token after open bracket\n'
|
||||
msg += f'token is "{line}\n"'
|
||||
raise self.__bug_handler
|
||||
elif self.__run_level > 3:
|
||||
msg = 'No matching token after open bracket\n'
|
||||
msg += f'token is "{line}\n"'
|
||||
raise self.__bug_handler
|
||||
|
||||
def __add_to_final_line(self):
|
||||
'''
|
||||
|
||||
@@ -411,11 +411,10 @@ class MakeLists:
|
||||
if self.__style_name in self.__headings:
|
||||
if self.__headings_to_sections:
|
||||
return 1
|
||||
elif self.__no_headings_as_list:
|
||||
return 1
|
||||
else:
|
||||
if self.__no_headings_as_list:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 0
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
@@ -160,27 +160,25 @@ class ParseOptions:
|
||||
# option and argument already paired
|
||||
elif '=' in arg:
|
||||
new_system_string .append(arg)
|
||||
else:
|
||||
# this option takes an argument
|
||||
if arg in self.__opt_with_args:
|
||||
# option is the last in the list
|
||||
if counter + 1 > opt_len:
|
||||
sys.stderr.write(f'option "{arg}" must take an argument\n')
|
||||
new_system_string.append(arg)
|
||||
self.__options_okay = 0
|
||||
else:
|
||||
# the next item in list is also an option
|
||||
if self.__system_string[counter][0] == '-':
|
||||
sys.stderr.write(f'option "{arg}" must take an argument\n')
|
||||
new_system_string.append(arg)
|
||||
self.__options_okay = 0
|
||||
# the next item in the list is the argument
|
||||
else:
|
||||
new_system_string.append(arg + '=' + self.__system_string[counter])
|
||||
slurp_value = 1
|
||||
# this option does not take an argument
|
||||
else:
|
||||
# this option takes an argument
|
||||
elif arg in self.__opt_with_args:
|
||||
# option is the last in the list
|
||||
if counter + 1 > opt_len:
|
||||
sys.stderr.write(f'option "{arg}" must take an argument\n')
|
||||
new_system_string.append(arg)
|
||||
self.__options_okay = 0
|
||||
# the next item in list is also an option
|
||||
elif self.__system_string[counter][0] == '-':
|
||||
sys.stderr.write(f'option "{arg}" must take an argument\n')
|
||||
new_system_string.append(arg)
|
||||
self.__options_okay = 0
|
||||
# the next item in the list is the argument
|
||||
else:
|
||||
new_system_string.append(arg + '=' + self.__system_string[counter])
|
||||
slurp_value = 1
|
||||
# this option does not take an argument
|
||||
else:
|
||||
new_system_string.append(arg)
|
||||
return new_system_string
|
||||
|
||||
def __get_just_options(self):
|
||||
|
||||
@@ -372,10 +372,9 @@ if another paragraph_def is found, the state changes to collect_tokens.
|
||||
type = self.__tab_type_dict.get(self.__token_info)
|
||||
if type is not None:
|
||||
self.__tab_type = type
|
||||
else:
|
||||
if self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
elif self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
|
||||
def __tab_leader_func(self, line):
|
||||
'''
|
||||
@@ -383,10 +382,9 @@ if another paragraph_def is found, the state changes to collect_tokens.
|
||||
leader = self.__tab_type_dict.get(self.__token_info)
|
||||
if leader is not None:
|
||||
self.__att_val_dict['tabs'] += f'{leader}^'
|
||||
else:
|
||||
if self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
elif self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
|
||||
def __tab_bar_func(self, line):
|
||||
'''
|
||||
|
||||
@@ -347,10 +347,9 @@ class Styles:
|
||||
type = self.__tab_type_dict.get(self.__token_info)
|
||||
if type is not None:
|
||||
self.__tab_type = type
|
||||
else:
|
||||
if self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
elif self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
|
||||
def __tab_leader_func(self, line):
|
||||
'''
|
||||
@@ -372,10 +371,9 @@ class Styles:
|
||||
except KeyError:
|
||||
self.__enter_dict_entry('tabs', '')
|
||||
self.__styles_dict['par'][self.__styles_num]['tabs'] += f'{leader};'
|
||||
else:
|
||||
if self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
elif self.__run_level > 3:
|
||||
msg = f'no entry for {self.__token_info}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
|
||||
def __tab_bar_func(self, line):
|
||||
'''
|
||||
@@ -439,10 +437,9 @@ class Styles:
|
||||
type_dict = self.__styles_dict['par']
|
||||
elif self.__type_of_style == 'char':
|
||||
type_dict = self.__styles_dict['char']
|
||||
else:
|
||||
if self.__run_level > 3:
|
||||
msg = self.__type_of_style + 'error\n'
|
||||
raise self.__bug_handler(msg)
|
||||
elif self.__run_level > 3:
|
||||
msg = self.__type_of_style + 'error\n'
|
||||
raise self.__bug_handler(msg)
|
||||
smallest_dict = {}
|
||||
smallest_dict[att] = value
|
||||
type_dict[self.__styles_num] = smallest_dict
|
||||
@@ -548,11 +545,10 @@ class Styles:
|
||||
else:
|
||||
if value == 0 or value == '0':
|
||||
pass
|
||||
else:
|
||||
if self.__run_level > 4:
|
||||
msg = f'{type} {key} is based on {value}\n'
|
||||
msg = f'There is no style with {value}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
elif self.__run_level > 4:
|
||||
msg = f'{type} {key} is based on {value}\n'
|
||||
msg = f'There is no style with {value}\n'
|
||||
raise self.__bug_handler(msg)
|
||||
del self.__styles_dict[type][key][style]
|
||||
|
||||
def __print_style_table(self):
|
||||
|
||||
@@ -186,23 +186,22 @@ class SNBMLizer:
|
||||
# Space was found.
|
||||
short_lines.append(line[:space])
|
||||
line = line[space + 1:]
|
||||
# Space was not found.
|
||||
elif False and self.opts.force_max_line_length:
|
||||
# Force breaking at max_lenght.
|
||||
short_lines.append(line[:max_length])
|
||||
line = line[max_length:]
|
||||
else:
|
||||
# Space was not found.
|
||||
if False and self.opts.force_max_line_length:
|
||||
# Force breaking at max_lenght.
|
||||
short_lines.append(line[:max_length])
|
||||
line = line[max_length:]
|
||||
# Look for the first space after max_length.
|
||||
space = line.find(' ', max_length, len(line))
|
||||
if space != -1:
|
||||
# Space was found.
|
||||
short_lines.append(line[:space])
|
||||
line = line[space + 1:]
|
||||
else:
|
||||
# Look for the first space after max_length.
|
||||
space = line.find(' ', max_length, len(line))
|
||||
if space != -1:
|
||||
# Space was found.
|
||||
short_lines.append(line[:space])
|
||||
line = line[space + 1:]
|
||||
else:
|
||||
# No space was found cannot break line.
|
||||
short_lines.append(line)
|
||||
line = ''
|
||||
# No space was found cannot break line.
|
||||
short_lines.append(line)
|
||||
line = ''
|
||||
# Add the text that was less than max_lengh to the list
|
||||
short_lines.append(line)
|
||||
text = '\n'.join(short_lines)
|
||||
|
||||
@@ -427,15 +427,14 @@ class TextileMLizer(OEB2HTML):
|
||||
text.append('&')
|
||||
tags.append('&')
|
||||
self.style_smallcap = True
|
||||
else:
|
||||
if self.in_a_link == False: # noqa: E712
|
||||
txt = '%'
|
||||
if self.opts.keep_links:
|
||||
txt += self.check_id_tag(attribs)
|
||||
txt += self.check_styles(style)
|
||||
if txt != '%':
|
||||
text.append(txt)
|
||||
tags.append('%')
|
||||
elif self.in_a_link == False: # noqa: E712
|
||||
txt = '%'
|
||||
if self.opts.keep_links:
|
||||
txt += self.check_id_tag(attribs)
|
||||
txt += self.check_styles(style)
|
||||
if txt != '%':
|
||||
text.append(txt)
|
||||
tags.append('%')
|
||||
|
||||
if self.opts.keep_links and 'id' in attribs:
|
||||
if tag not in ('body', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'table'):
|
||||
|
||||
@@ -159,23 +159,22 @@ class TXTMLizer:
|
||||
# Space was found.
|
||||
short_lines.append(line[:space])
|
||||
line = line[space + 1:]
|
||||
# Space was not found.
|
||||
elif self.opts.force_max_line_length:
|
||||
# Force breaking at max_lenght.
|
||||
short_lines.append(line[:max_length])
|
||||
line = line[max_length:]
|
||||
else:
|
||||
# Space was not found.
|
||||
if self.opts.force_max_line_length:
|
||||
# Force breaking at max_lenght.
|
||||
short_lines.append(line[:max_length])
|
||||
line = line[max_length:]
|
||||
# Look for the first space after max_length.
|
||||
space = line.find(' ', max_length, len(line))
|
||||
if space != -1:
|
||||
# Space was found.
|
||||
short_lines.append(line[:space])
|
||||
line = line[space + 1:]
|
||||
else:
|
||||
# Look for the first space after max_length.
|
||||
space = line.find(' ', max_length, len(line))
|
||||
if space != -1:
|
||||
# Space was found.
|
||||
short_lines.append(line[:space])
|
||||
line = line[space + 1:]
|
||||
else:
|
||||
# No space was found cannot break line.
|
||||
short_lines.append(line)
|
||||
line = ''
|
||||
# No space was found cannot break line.
|
||||
short_lines.append(line)
|
||||
line = ''
|
||||
# Add the text that was less than max_lengh to the list
|
||||
short_lines.append(line)
|
||||
text = '\n'.join(short_lines)
|
||||
|
||||
@@ -1349,10 +1349,9 @@ class Application(QApplication):
|
||||
f.setFamily('Segoe UI')
|
||||
f.setPointSize(9)
|
||||
QApplication.setFont(f)
|
||||
else:
|
||||
if q == ('Sans Serif', 9): # Hard coded Qt settings, no user preference detected
|
||||
f.setPointSize(10)
|
||||
QApplication.setFont(f)
|
||||
elif q == ('Sans Serif', 9): # Hard coded Qt settings, no user preference detected
|
||||
f.setPointSize(10)
|
||||
QApplication.setFont(f)
|
||||
f = QFontInfo(f)
|
||||
self.original_font = (f.family(), f.pointSize(), f.weight(), f.italic(), 100)
|
||||
|
||||
|
||||
@@ -411,11 +411,10 @@ class Adder(QObject):
|
||||
a(_('With error:')), a(traceback.format_exc())
|
||||
else:
|
||||
self.add_book(mi, cover_path, paths)
|
||||
elif duplicate_info or icu_lower(mi.title or _('Unknown')) in self.added_duplicate_info:
|
||||
self.duplicates.append((mi, cover_path, paths))
|
||||
else:
|
||||
if duplicate_info or icu_lower(mi.title or _('Unknown')) in self.added_duplicate_info:
|
||||
self.duplicates.append((mi, cover_path, paths))
|
||||
else:
|
||||
self.add_book(mi, cover_path, paths)
|
||||
self.add_book(mi, cover_path, paths)
|
||||
|
||||
def merge_books(self, mi, cover_path, paths, identical_book_ids):
|
||||
self.merged_books.add((mi.title, ' & '.join(mi.authors)))
|
||||
|
||||
+14
-17
@@ -92,31 +92,28 @@ def wrap_button_text(text, max_len=MAX_TEXT_LENGTH):
|
||||
for word in parts:
|
||||
if broken:
|
||||
ans += ' ' + word
|
||||
else:
|
||||
if len(ans) + len(word) < max_len:
|
||||
if ans:
|
||||
ans += ' ' + word
|
||||
else:
|
||||
ans = word
|
||||
elif len(ans) + len(word) < max_len:
|
||||
if ans:
|
||||
ans += ' ' + word
|
||||
else:
|
||||
if ans:
|
||||
ans += '\n' + word
|
||||
broken = True
|
||||
else:
|
||||
ans = word
|
||||
ans = word
|
||||
elif ans:
|
||||
ans += '\n' + word
|
||||
broken = True
|
||||
else:
|
||||
ans = word
|
||||
if broken:
|
||||
prefix, suffix = ans.split('\n', 1)
|
||||
if len(suffix) > len(prefix) and len(suffix) > MAX_TEXT_LENGTH and len(prefix) < MAX_TEXT_LENGTH and suffix.count(' ') > 1:
|
||||
word, rest = suffix.split(' ', 1)
|
||||
if len(word) + len(prefix) <= len(rest):
|
||||
ans = prefix + ' ' + word + '\n' + rest
|
||||
elif ' ' in ans:
|
||||
ans = '\n'.join(ans.split(' ', 1))
|
||||
elif '/' in ans:
|
||||
ans = '/\n'.join(ans.split('/', 1))
|
||||
else:
|
||||
if ' ' in ans:
|
||||
ans = '\n'.join(ans.split(' ', 1))
|
||||
elif '/' in ans:
|
||||
ans = '/\n'.join(ans.split('/', 1))
|
||||
else:
|
||||
ans += '\n\xa0'
|
||||
ans += '\n\xa0'
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
@@ -757,12 +757,11 @@ def details_context_menu_event(view, ev, book_info, add_popup_action=False, edit
|
||||
from calibre.gui2.ui import get_gui
|
||||
if add_popup_action:
|
||||
menu.addMenu(get_gui().iactions['Show Book Details'].qaction.menu())
|
||||
else:
|
||||
# We can't open edit metadata from a locked window because EM expects to
|
||||
# be editing the current book, which this book probably isn't
|
||||
if edit_metadata is not None:
|
||||
ema = get_gui().iactions['Edit Metadata'].menuless_qaction
|
||||
menu.addAction(_('Open the Edit metadata window') + '\t' + ema.shortcut().toString(QKeySequence.SequenceFormat.NativeText), edit_metadata)
|
||||
# We can't open edit metadata from a locked window because EM expects to
|
||||
# be editing the current book, which this book probably isn't
|
||||
elif edit_metadata is not None:
|
||||
ema = get_gui().iactions['Edit Metadata'].menuless_qaction
|
||||
menu.addAction(_('Open the Edit metadata window') + '\t' + ema.shortcut().toString(QKeySequence.SequenceFormat.NativeText), edit_metadata)
|
||||
if not reindex_fmt_added:
|
||||
menu.addSeparator()
|
||||
menu.addAction(_(
|
||||
|
||||
@@ -859,11 +859,10 @@ class CheckableTableWidgetItem(QTableWidgetItem):
|
||||
self.setFlags(self.flags() | Qt.ItemFlag.ItemIsTristate)
|
||||
if checked:
|
||||
self.setCheckState(Qt.CheckState.Checked)
|
||||
elif is_tristate and checked is None:
|
||||
self.setCheckState(Qt.CheckState.PartiallyChecked)
|
||||
else:
|
||||
if is_tristate and checked is None:
|
||||
self.setCheckState(Qt.CheckState.PartiallyChecked)
|
||||
else:
|
||||
self.setCheckState(Qt.CheckState.Unchecked)
|
||||
self.setCheckState(Qt.CheckState.Unchecked)
|
||||
|
||||
def get_boolean_value(self):
|
||||
'''
|
||||
@@ -1162,17 +1161,16 @@ class GenericRulesTable(QTableWidget):
|
||||
values = []
|
||||
elif source_field == _('Tags'):
|
||||
values = sorted(self.db.all_tags(), key=sort_key)
|
||||
else:
|
||||
if self.eligible_custom_fields[str(source_field)]['datatype'] in ['enumeration', 'text']:
|
||||
values = self.db.all_custom(self.db.field_metadata.key_to_label(
|
||||
self.eligible_custom_fields[str(source_field)]['field']))
|
||||
values = sorted(values, key=sort_key)
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['bool']:
|
||||
values = [_('True'),_('False'),_('unspecified')]
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['composite']:
|
||||
values = [_('any value'),_('unspecified')]
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['datetime']:
|
||||
values = [_('any date'),_('unspecified')]
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['enumeration', 'text']:
|
||||
values = self.db.all_custom(self.db.field_metadata.key_to_label(
|
||||
self.eligible_custom_fields[str(source_field)]['field']))
|
||||
values = sorted(values, key=sort_key)
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['bool']:
|
||||
values = [_('True'),_('False'),_('unspecified')]
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['composite']:
|
||||
values = [_('any value'),_('unspecified')]
|
||||
elif self.eligible_custom_fields[str(source_field)]['datatype'] in ['datetime']:
|
||||
values = [_('any date'),_('unspecified')]
|
||||
|
||||
values_combo = ComboBox(self, values, pattern)
|
||||
values_combo.currentIndexChanged.connect(partial(self.values_index_changed, values_combo))
|
||||
|
||||
@@ -1400,11 +1400,10 @@ class Highlighter(QSyntaxHighlighter):
|
||||
if ch == '<':
|
||||
if text[pos:pos+4] == '<!--':
|
||||
state = State_Comment
|
||||
elif text[pos:pos+9].upper() == '<!DOCTYPE':
|
||||
state = State_DocType
|
||||
else:
|
||||
if text[pos:pos+9].upper() == '<!DOCTYPE':
|
||||
state = State_DocType
|
||||
else:
|
||||
state = State_TagStart
|
||||
state = State_TagStart
|
||||
break
|
||||
elif ch == '&':
|
||||
start = pos
|
||||
|
||||
+16
-19
@@ -913,19 +913,18 @@ class DeviceMenu(QMenu): # {{{
|
||||
if action.dest in ('main:', 'carda:0', 'cardb:0'):
|
||||
if not enable:
|
||||
action.setEnabled(False)
|
||||
else:
|
||||
if action.dest == 'main:':
|
||||
elif action.dest == 'main:':
|
||||
action.setEnabled(True)
|
||||
elif action.dest == 'carda:0':
|
||||
if card_prefix and card_prefix[0] is not None:
|
||||
action.setEnabled(True)
|
||||
elif action.dest == 'carda:0':
|
||||
if card_prefix and card_prefix[0] is not None:
|
||||
action.setEnabled(True)
|
||||
else:
|
||||
action.setEnabled(False)
|
||||
elif action.dest == 'cardb:0':
|
||||
if card_prefix and card_prefix[1] is not None:
|
||||
action.setEnabled(True)
|
||||
else:
|
||||
action.setEnabled(False)
|
||||
else:
|
||||
action.setEnabled(False)
|
||||
elif action.dest == 'cardb:0':
|
||||
if card_prefix and card_prefix[1] is not None:
|
||||
action.setEnabled(True)
|
||||
else:
|
||||
action.setEnabled(False)
|
||||
|
||||
annot_enable = enable and getattr(device, 'SUPPORTS_ANNOTATIONS', False)
|
||||
self.annotation_action.setEnabled(annot_enable)
|
||||
@@ -1623,11 +1622,10 @@ class DeviceMixin: # {{{
|
||||
auto.append(id)
|
||||
else:
|
||||
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||
elif specific_format in list(set(settings.format_map).intersection(set(available_output_formats()))):
|
||||
auto.append(id)
|
||||
else:
|
||||
if specific_format in list(set(settings.format_map).intersection(set(available_output_formats()))):
|
||||
auto.append(id)
|
||||
else:
|
||||
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||
|
||||
if auto != []:
|
||||
format = specific_format if specific_format in \
|
||||
@@ -2091,9 +2089,8 @@ class DeviceMixin: # {{{
|
||||
except Exception:
|
||||
prints('Problem creating temporary file for', fmt_name)
|
||||
traceback.print_exc()
|
||||
else:
|
||||
if DEBUG:
|
||||
prints("DeviceJob: book doesn't have that format")
|
||||
elif DEBUG:
|
||||
prints("DeviceJob: book doesn't have that format")
|
||||
if files:
|
||||
self.upload_books(files, names, metadata)
|
||||
except Exception:
|
||||
|
||||
@@ -130,9 +130,8 @@ class AddFromISBN(QDialog):
|
||||
self.books.append({'isbn': isbn, 'path': path, '': 'isbn'})
|
||||
else:
|
||||
bad.add(parts[0])
|
||||
else:
|
||||
if prefix != 'path':
|
||||
self.books.append({prefix: val, 'path': path, '':prefix})
|
||||
elif prefix != 'path':
|
||||
self.books.append({prefix: val, 'path': path, '':prefix})
|
||||
if bad:
|
||||
if self.books:
|
||||
if not question_dialog(self, _('Some invalid ISBNs'),
|
||||
|
||||
@@ -214,10 +214,9 @@ class ChooseMerge(Dialog):
|
||||
msg += '<br><br>' + _(
|
||||
'Any duplicate formats in the selected books '
|
||||
'will be permanently <b>deleted</b> from your calibre library.')
|
||||
else:
|
||||
if mf:
|
||||
msg += _(
|
||||
'Any formats not in the target book will be added to it from the selected books.')
|
||||
elif mf:
|
||||
msg += _(
|
||||
'Any formats not in the target book will be added to it from the selected books.')
|
||||
if not msg.endswith('<br>'):
|
||||
msg += '<br><br>'
|
||||
|
||||
|
||||
@@ -482,11 +482,10 @@ class DisplayPluginModel(QAbstractTableModel):
|
||||
icon_name = 'plugin_upgrade_invalid.png'
|
||||
else:
|
||||
icon_name = 'plugin_upgrade_ok.png'
|
||||
else: # A plugin available not currently installed
|
||||
if display_plugin.is_valid_to_install():
|
||||
icon_name = 'plugin_new_valid.png'
|
||||
else:
|
||||
icon_name = 'plugin_new_invalid.png'
|
||||
elif display_plugin.is_valid_to_install():
|
||||
icon_name = 'plugin_new_valid.png'
|
||||
else:
|
||||
icon_name = 'plugin_new_invalid.png'
|
||||
return QIcon.ic('plugins/' + icon_name)
|
||||
|
||||
def _get_status_tooltip(self, display_plugin):
|
||||
|
||||
@@ -446,13 +446,12 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
self.set_search_text(col+ ':="' + t + '"')
|
||||
else:
|
||||
self.set_search_text(None)
|
||||
elif self.fm[col]['is_multiple']:
|
||||
items = [(col + ':"=' + v.strip() + '"') for v in
|
||||
current.text().split(self.fm[col]['is_multiple']['ui_to_list'])]
|
||||
self.set_search_text(' and '.join(items))
|
||||
else:
|
||||
if self.fm[col]['is_multiple']:
|
||||
items = [(col + ':"=' + v.strip() + '"') for v in
|
||||
current.text().split(self.fm[col]['is_multiple']['ui_to_list'])]
|
||||
self.set_search_text(' and '.join(items))
|
||||
else:
|
||||
self.set_search_text(col + ':"=' + current.text() + '"')
|
||||
self.set_search_text(col + ':"=' + current.text() + '"')
|
||||
|
||||
def tab_pressed(self, in_widget, isForward):
|
||||
if isForward:
|
||||
|
||||
@@ -67,11 +67,10 @@ class ShowNoteDialog(Dialog):
|
||||
l1 = self.extra_link
|
||||
l1tt = self.extra_link_tooltip
|
||||
l2 = self.item_link
|
||||
elif self.item_link:
|
||||
l1 = self.item_link
|
||||
else:
|
||||
if self.item_link:
|
||||
l1 = self.item_link
|
||||
else:
|
||||
l2, l2tt = self.extra_link, self.extra_link_tooltip
|
||||
l2, l2tt = self.extra_link, self.extra_link_tooltip
|
||||
if l1:
|
||||
src = f'<a href="{x(l1, True)}" style="text-decoration: none" title="{x(l1tt, True)}">{src}</a>'
|
||||
if l2:
|
||||
|
||||
@@ -185,16 +185,15 @@ class NotesUtilities:
|
||||
else:
|
||||
item.setIcon(QIcon.cached_icon('notes.png'))
|
||||
item.set_sort_val(NotesTableWidgetItem.UNCHANGED)
|
||||
elif has_value:
|
||||
item.setIcon(QIcon.cached_icon('modified.png'))
|
||||
item.set_sort_val(NotesTableWidgetItem.EDITED)
|
||||
elif not bool(self.modified_notes[id_]):
|
||||
item.setIcon(QIcon.cached_icon())
|
||||
item.set_sort_val(NotesTableWidgetItem.EMPTY)
|
||||
else:
|
||||
if has_value:
|
||||
item.setIcon(QIcon.cached_icon('modified.png'))
|
||||
item.set_sort_val(NotesTableWidgetItem.EDITED)
|
||||
elif not bool(self.modified_notes[id_]):
|
||||
item.setIcon(QIcon.cached_icon())
|
||||
item.set_sort_val(NotesTableWidgetItem.EMPTY)
|
||||
else:
|
||||
item.setIcon(QIcon.cached_icon('trash.png'))
|
||||
item.set_sort_val(NotesTableWidgetItem.DELETED)
|
||||
item.setIcon(QIcon.cached_icon('trash.png'))
|
||||
item.set_sort_val(NotesTableWidgetItem.DELETED)
|
||||
self.table.cellChanged.emit(item.row(), item.column())
|
||||
self.table.itemChanged.emit(item)
|
||||
|
||||
|
||||
@@ -469,11 +469,10 @@ class EmailMixin: # {{{
|
||||
auto.append(id)
|
||||
else:
|
||||
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||
elif specific_format in list(set(fmts).intersection(set(available_output_formats()))):
|
||||
auto.append(id)
|
||||
else:
|
||||
if specific_format in list(set(fmts).intersection(set(available_output_formats()))):
|
||||
auto.append(id)
|
||||
else:
|
||||
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||
|
||||
if auto != []:
|
||||
format = specific_format if specific_format in list(set(fmts).intersection(set(available_output_formats()))) else None
|
||||
|
||||
@@ -68,15 +68,14 @@ def jump_to_book(book_id, parent=None):
|
||||
parent = parent or gui
|
||||
if gui.library_view.select_rows((book_id,)):
|
||||
gui.raise_and_focus()
|
||||
elif gprefs['fts_library_restrict_books']:
|
||||
error_dialog(parent, _('Not found'), _('This book was not found in the calibre library'), show=True)
|
||||
else:
|
||||
if gprefs['fts_library_restrict_books']:
|
||||
error_dialog(parent, _('Not found'), _('This book was not found in the calibre library'), show=True)
|
||||
else:
|
||||
error_dialog(parent, _('Not found'), _(
|
||||
'This book is not currently visible in the calibre library.'
|
||||
' If you have a search or Virtual library active, try clearing that.'
|
||||
' Or click the "Restrict searched books" checkbox in this window to'
|
||||
' only search currently visible books.'), show=True)
|
||||
error_dialog(parent, _('Not found'), _(
|
||||
'This book is not currently visible in the calibre library.'
|
||||
' If you have a search or Virtual library active, try clearing that.'
|
||||
' Or click the "Restrict searched books" checkbox in this window to'
|
||||
' only search currently visible books.'), show=True)
|
||||
|
||||
|
||||
def show_in_viewer(book_id, text, fmt):
|
||||
|
||||
@@ -373,11 +373,10 @@ class ImageView(QDialog):
|
||||
if on:
|
||||
self.maximized_at_last_fullscreen = self.isMaximized()
|
||||
self.showFullScreen()
|
||||
elif self.maximized_at_last_fullscreen:
|
||||
self.showMaximized()
|
||||
else:
|
||||
if self.maximized_at_last_fullscreen:
|
||||
self.showMaximized()
|
||||
else:
|
||||
self.showNormal()
|
||||
self.showNormal()
|
||||
|
||||
|
||||
class ImagePopup:
|
||||
|
||||
@@ -185,10 +185,9 @@ def render_notes(notes, tag='p'):
|
||||
for line in notes.splitlines():
|
||||
if line:
|
||||
current_lines.append(''.join(render_note_line(line)))
|
||||
else:
|
||||
if current_lines:
|
||||
yield '<{0}>{1}</{0}>'.format(tag, '\n'.join(current_lines))
|
||||
current_lines = []
|
||||
elif current_lines:
|
||||
yield '<{0}>{1}</{0}>'.format(tag, '\n'.join(current_lines))
|
||||
current_lines = []
|
||||
if current_lines:
|
||||
yield '<{0}>{1}</{0}>'.format(tag, '\n'.join(current_lines))
|
||||
|
||||
|
||||
@@ -887,16 +887,15 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
if val is None:
|
||||
return None
|
||||
return by if val else bn
|
||||
elif m['display'].get('bools_show_icons', True):
|
||||
def func(idx):
|
||||
val = force_to_bool(fffunc(field_obj, idfunc(idx)))
|
||||
if val is None:
|
||||
return None if bt else bn
|
||||
return by if val else bn
|
||||
else:
|
||||
if m['display'].get('bools_show_icons', True):
|
||||
def func(idx):
|
||||
val = force_to_bool(fffunc(field_obj, idfunc(idx)))
|
||||
if val is None:
|
||||
return None if bt else bn
|
||||
return by if val else bn
|
||||
else:
|
||||
def func(idx):
|
||||
return None
|
||||
def func(idx):
|
||||
return None
|
||||
elif field == 'size':
|
||||
sz_mult = 1/(1024**2)
|
||||
|
||||
@@ -929,21 +928,19 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
else:
|
||||
def func(idx):
|
||||
return (fffunc(field_obj, idfunc(idx), default_value=''))
|
||||
elif do_sort:
|
||||
def func(idx):
|
||||
return (jv.join(sorted(fffunc(field_obj, idfunc(idx), default_value=()), key=sort_key)))
|
||||
else:
|
||||
if do_sort:
|
||||
def func(idx):
|
||||
return (jv.join(sorted(fffunc(field_obj, idfunc(idx), default_value=()), key=sort_key)))
|
||||
else:
|
||||
def func(idx):
|
||||
return (jv.join(fffunc(field_obj, idfunc(idx), default_value=())))
|
||||
def func(idx):
|
||||
return (jv.join(fffunc(field_obj, idfunc(idx), default_value=())))
|
||||
elif dt in {'text', 'composite', 'enumeration'} and m['display'].get('use_decorations', False):
|
||||
def func(idx):
|
||||
text = fffunc(field_obj, idfunc(idx))
|
||||
return (text) if force_to_bool(text) is None else None
|
||||
else:
|
||||
if dt in {'text', 'composite', 'enumeration'} and m['display'].get('use_decorations', False):
|
||||
def func(idx):
|
||||
text = fffunc(field_obj, idfunc(idx))
|
||||
return (text) if force_to_bool(text) is None else None
|
||||
else:
|
||||
def func(idx):
|
||||
return fffunc(field_obj, idfunc(idx), default_value='')
|
||||
def func(idx):
|
||||
return fffunc(field_obj, idfunc(idx), default_value='')
|
||||
elif dt == 'datetime':
|
||||
def func(idx):
|
||||
val = fffunc(field_obj, idfunc(idx), default_value=UNDEFINED_DATE)
|
||||
|
||||
@@ -40,16 +40,15 @@ class Listener(QLocalServer):
|
||||
s.listen(16)
|
||||
if not self.listen(s.detach()):
|
||||
raise OSError(f'Could not start Listener for IPC at address @{self.address[1:]} with error: {self.errorString()}')
|
||||
else:
|
||||
if not self.listen(self.address): # Qt sets bhandleInteritable = False so not inheritable
|
||||
if self.serverError() == QAbstractSocket.SocketError.AddressInUseError and self.uses_filesystem:
|
||||
self.removeServer(self.address)
|
||||
if self.listen(self.address):
|
||||
return
|
||||
code = self.serverError()
|
||||
if code == QAbstractSocket.SocketError.AddressInUseError:
|
||||
raise OSError(errno.EADDRINUSE, os.strerror(errno.EADDRINUSE), self.address)
|
||||
raise OSError(f'Could not start Listener for IPC at address {self.address} with error: {self.errorString()}')
|
||||
elif not self.listen(self.address): # Qt sets bhandleInteritable = False so not inheritable
|
||||
if self.serverError() == QAbstractSocket.SocketError.AddressInUseError and self.uses_filesystem:
|
||||
self.removeServer(self.address)
|
||||
if self.listen(self.address):
|
||||
return
|
||||
code = self.serverError()
|
||||
if code == QAbstractSocket.SocketError.AddressInUseError:
|
||||
raise OSError(errno.EADDRINUSE, os.strerror(errno.EADDRINUSE), self.address)
|
||||
raise OSError(f'Could not start Listener for IPC at address {self.address} with error: {self.errorString()}')
|
||||
|
||||
def on_new_connection(self):
|
||||
while True:
|
||||
|
||||
@@ -418,12 +418,11 @@ def run_gui_(opts, args, app, gui_debug=None):
|
||||
after_quit_actions['restart_after_quit'] = True
|
||||
after_quit_actions['debug_on_restart'] = getattr(runner.main, 'debug_on_restart', False) or gui_debug is not None
|
||||
after_quit_actions['no_plugins_on_restart'] = getattr(runner.main, 'no_plugins_on_restart', False)
|
||||
else:
|
||||
if iswindows:
|
||||
try:
|
||||
runner.main.system_tray_icon.hide()
|
||||
except Exception:
|
||||
pass
|
||||
elif iswindows:
|
||||
try:
|
||||
runner.main.system_tray_icon.hide()
|
||||
except Exception:
|
||||
pass
|
||||
if getattr(runner.main, 'gui_debug', None) is not None:
|
||||
debugfile = runner.main.gui_debug
|
||||
from calibre.gui2 import open_local_file
|
||||
|
||||
@@ -153,11 +153,10 @@ class MainWindow(QMainWindow):
|
||||
dmsg = _('The folder "{}" is opened in another program, so calibre cannot access it.').format(fname)
|
||||
else:
|
||||
dmsg = _('The file "{}" is opened in another program, so calibre cannot access it.').format(fname)
|
||||
elif is_folder:
|
||||
dmsg = _('A folder is open in another program so calibre cannot access it.')
|
||||
else:
|
||||
if is_folder:
|
||||
dmsg = _('A folder is open in another program so calibre cannot access it.')
|
||||
else:
|
||||
dmsg = _('A file is open in another program so calibre cannot access it.')
|
||||
dmsg = _('A file is open in another program so calibre cannot access it.')
|
||||
if is_folder:
|
||||
dmsg += _('This is usually caused by leaving Windows explorer or a similar file manager open'
|
||||
' to a folder in the calibre library. Close Windows explorer and retry.')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user