mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
commit
b25f94275c
@ -30,7 +30,7 @@
|
||||
|
||||
- title: "Book details panel: Clicking an author name now searches Goodreads by default instead of Wikipedia. Can be changed in Preferences->Interface->Look & feel->Book details"
|
||||
|
||||
- title: "Kobo driver: Add support for the Kobo Auro H2O Edition 2"
|
||||
- title: "Kobo driver: Add support for the Kobo Aura H2O Edition 2"
|
||||
|
||||
bug fixes:
|
||||
- title: "PDF output: Fix a regression in the previous release that broke conversion to PDF for some files"
|
||||
@ -75,7 +75,7 @@
|
||||
|
||||
- title: "Add API to pre-process image data in recipes easily"
|
||||
|
||||
- title: "Fetch e-book metadata: add option to use only a single metadata plugin"
|
||||
- title: "fetch-ebook-metadata.exe: add option to use only a single metadata plugin"
|
||||
|
||||
bug fixes:
|
||||
- title: "E-book viewer: Fix a regression in the previous release that broke printing from inside the viewer"
|
||||
@ -152,7 +152,7 @@
|
||||
- title: "PDF output: Fix a regression that broke PDF output for documents containing mathematics"
|
||||
tickets: [1673983]
|
||||
|
||||
- title: "E-book viewer: Fix a regression that broke the Clear recently read books' action in the viewer"
|
||||
- title: 'E-book viewer: Fix a regression that broke the "Clear recently read books" action in the viewer'
|
||||
|
||||
improved recipes:
|
||||
- Go Comics
|
||||
@ -463,7 +463,7 @@
|
||||
|
||||
- title: "Add support for new Kobo firmware version 4.2"
|
||||
|
||||
- title: "Allow using Amazon_in, Amazon_au, Amazon_com identifiers in the Book details panel"
|
||||
- title: "Allow using amazon_in, amazon_au, amazon_com identifiers in the Book details panel"
|
||||
tickets: [1649371]
|
||||
|
||||
bug fixes:
|
||||
@ -477,7 +477,7 @@
|
||||
- title: "Edit book: Fix the 'Search ignoring markup tool' not ignoring comments/processing instructions, etc"
|
||||
tickets: [1651160]
|
||||
|
||||
- title: "CSS Transforms: Fix 'is'/'is not' rules not matching current color"
|
||||
- title: "CSS Transforms: Fix 'is'/'is not' rules not matching 'currentColor'"
|
||||
tickets: [1650930]
|
||||
|
||||
- title: "E-book viewer: Make the swipe up gesture move to next section instead of previous section"
|
||||
|
@ -231,7 +231,8 @@ class NYTimes(BasicNewsRecipe):
|
||||
re.compile('commentCount'),
|
||||
'lede-container',
|
||||
'credit',
|
||||
'caption-video'
|
||||
'caption-video',
|
||||
'upshot-social'
|
||||
]}),
|
||||
dict(
|
||||
attrs={'class': lambda x: x and 'related-coverage-marginalia' in x.split()}),
|
||||
|
@ -231,7 +231,8 @@ class NYTimes(BasicNewsRecipe):
|
||||
re.compile('commentCount'),
|
||||
'lede-container',
|
||||
'credit',
|
||||
'caption-video'
|
||||
'caption-video',
|
||||
'upshot-social'
|
||||
]}),
|
||||
dict(
|
||||
attrs={'class': lambda x: x and 'related-coverage-marginalia' in x.split()}),
|
||||
|
@ -20,6 +20,7 @@ from calibre.utils.localization import canonicalize_lang
|
||||
readonly = False
|
||||
version = 0 # change this if you change signature of implementation()
|
||||
|
||||
|
||||
def to_stream(data):
|
||||
ans = BytesIO(data[1])
|
||||
ans.name = data[0]
|
||||
|
@ -25,6 +25,7 @@ from calibre.utils.localization import calibre_langcode_to_name
|
||||
def bool_sort_key(bools_are_tristate):
|
||||
return (lambda x:{True: 1, False: 2, None: 3}.get(x, 3)) if bools_are_tristate else lambda x:{True: 1, False: 2, None: 2}.get(x, 2)
|
||||
|
||||
|
||||
IDENTITY = lambda x: x
|
||||
|
||||
|
||||
@ -756,4 +757,3 @@ def create_field(name, table, bools_are_tristate, get_template_functions):
|
||||
elif table.metadata['datatype'] == 'series':
|
||||
cls = SeriesField
|
||||
return cls(name, table, bools_are_tristate, get_template_functions)
|
||||
|
||||
|
@ -1451,15 +1451,15 @@ class KOBOTOUCH(KOBO):
|
||||
|
||||
def open_linux(self):
|
||||
super(KOBOTOUCH, self).open_linux()
|
||||
|
||||
|
||||
self.swap_drives_if_needed()
|
||||
|
||||
def open_osx(self):
|
||||
# Just dump some info to the logs.
|
||||
super(KOBOTOUCH, self).open_osx()
|
||||
|
||||
# Wrap some debugging output in a try/except so that it unlikely to break things completely.
|
||||
try:
|
||||
# Wrap some debugging output in a try/except so that it unlikely to break things completely.
|
||||
try:
|
||||
if DEBUG:
|
||||
from calibre.constants import plugins
|
||||
usbobserver, usbobserver_err = plugins['usbobserver']
|
||||
|
@ -201,6 +201,23 @@ class SearchBar(QFrame): # {{{
|
||||
self.vl_sep.setFrameStyle(QFrame.VLine | QFrame.Sunken)
|
||||
l.addWidget(self.vl_sep)
|
||||
|
||||
parent.sort_sep = QFrame(self)
|
||||
parent.sort_sep.setFrameStyle(QFrame.VLine | QFrame.Sunken)
|
||||
parent.sort_sep.setVisible(False)
|
||||
parent.sort_button = self.sort_button = sb = QToolButton(self)
|
||||
sb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
sb.setToolTip(_('Change how the displayed books are sorted'))
|
||||
sb.setCursor(Qt.PointingHandCursor)
|
||||
sb.setPopupMode(QToolButton.InstantPopup)
|
||||
sb.setAutoRaise(True)
|
||||
sb.setText(_('Sort'))
|
||||
sb.setIcon(QIcon(I('sort.png')))
|
||||
sb.setMenu(QMenu())
|
||||
sb.menu().aboutToShow.connect(self.populate_sort_menu)
|
||||
sb.setVisible(False)
|
||||
l.addWidget(sb)
|
||||
l.addWidget(parent.sort_sep)
|
||||
|
||||
x = parent.search = SearchBox2(self)
|
||||
x.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
x.setObjectName("search")
|
||||
@ -230,6 +247,10 @@ class SearchBar(QFrame): # {{{
|
||||
_('Do Quick Search (you can also press the Enter key)'))
|
||||
|
||||
x = parent.highlight_only_button = QToolButton(self)
|
||||
x.setAutoRaise(True)
|
||||
x.setText(_('Highlight'))
|
||||
x.setCursor(Qt.PointingHandCursor)
|
||||
x.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
x.setIcon(QIcon(I('arrow-down.png')))
|
||||
l.addWidget(x)
|
||||
|
||||
@ -270,23 +291,6 @@ class SearchBar(QFrame): # {{{
|
||||
l.addWidget(x)
|
||||
x.setVisible(not tweaks['show_saved_search_box'])
|
||||
|
||||
parent.sort_sep = QFrame(self)
|
||||
parent.sort_sep.setFrameStyle(QFrame.VLine | QFrame.Sunken)
|
||||
parent.sort_sep.setVisible(False)
|
||||
l.addWidget(parent.sort_sep)
|
||||
parent.sort_button = self.sort_button = sb = QToolButton(self)
|
||||
sb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
sb.setToolTip(_('Change how the displayed books are sorted'))
|
||||
sb.setCursor(Qt.PointingHandCursor)
|
||||
sb.setPopupMode(QToolButton.InstantPopup)
|
||||
sb.setAutoRaise(True)
|
||||
sb.setText(_('Sort'))
|
||||
sb.setIcon(QIcon(I('sort.png')))
|
||||
sb.setMenu(QMenu())
|
||||
sb.menu().aboutToShow.connect(self.populate_sort_menu)
|
||||
sb.setVisible(False)
|
||||
l.addWidget(sb)
|
||||
|
||||
def populate_sort_menu(self):
|
||||
from calibre.gui2.ui import get_gui
|
||||
get_gui().iactions['Sort By'].update_menu(self.sort_button.menu())
|
||||
|
@ -492,10 +492,13 @@ class SearchBoxMixin(object): # {{{
|
||||
self.focus_to_library()
|
||||
|
||||
def set_highlight_only_button_icon(self):
|
||||
b = self.highlight_only_button
|
||||
if config['highlight_search_matches']:
|
||||
self.highlight_only_button.setIcon(QIcon(I('highlight_only_on.png')))
|
||||
b.setIcon(QIcon(I('highlight_only_on.png')))
|
||||
b.setText(_('Filter'))
|
||||
else:
|
||||
self.highlight_only_button.setIcon(QIcon(I('highlight_only_off.png')))
|
||||
b.setIcon(QIcon(I('highlight_only_off.png')))
|
||||
b.setText(_('Highlight'))
|
||||
self.highlight_only_button.setVisible(gprefs['show_highlight_toggle_button'])
|
||||
self.library_view.model().set_highlight_only(config['highlight_search_matches'])
|
||||
|
||||
|
@ -341,6 +341,22 @@ class TagBrowserMixin(object): # {{{
|
||||
# }}}
|
||||
|
||||
|
||||
class FindBox(HistoryLineEdit): # {{{
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
k = event.key()
|
||||
if k not in (Qt.Key_Up, Qt.Key_Down):
|
||||
return HistoryLineEdit.keyPressEvent(self, event)
|
||||
self.blockSignals(True)
|
||||
if k == Qt.Key_Down and self.currentIndex() == 0 and not self.lineEdit().text():
|
||||
self.setCurrentIndex(1), self.setCurrentIndex(0)
|
||||
event.accept()
|
||||
else:
|
||||
HistoryLineEdit.keyPressEvent(self, event)
|
||||
self.blockSignals(False)
|
||||
# }}}
|
||||
|
||||
|
||||
class TagBrowserBar(QWidget): # {{{
|
||||
|
||||
def __init__(self, parent):
|
||||
@ -365,7 +381,7 @@ class TagBrowserBar(QWidget): # {{{
|
||||
self.label = la = QLabel(self)
|
||||
la.setText(_('Tag browser'))
|
||||
|
||||
self.item_search = HistoryLineEdit(parent)
|
||||
self.item_search = FindBox(parent)
|
||||
self.item_search.setMinimumContentsLength(5)
|
||||
self.item_search.setSizeAdjustPolicy(self.item_search.AdjustToMinimumContentsLengthWithIcon)
|
||||
self.item_search.initialize('tag_browser_search')
|
||||
@ -380,26 +396,24 @@ class TagBrowserBar(QWidget): # {{{
|
||||
ac = QAction(parent)
|
||||
parent.addAction(ac)
|
||||
parent.keyboard.register_shortcut('tag browser find box',
|
||||
_('Find item'), default_keys=(),
|
||||
_('Find next match'), default_keys=(),
|
||||
action=ac, group=_('Tag browser'))
|
||||
ac.triggered.connect(self.set_focus_to_find_box)
|
||||
|
||||
self.search_button = QToolButton()
|
||||
self.search_button.setCursor(Qt.PointingHandCursor)
|
||||
self.search_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
self.search_button.setIcon(QIcon(I('search.png')))
|
||||
self.search_button.setText(_('Find'))
|
||||
self.search_button.setToolTip(_('Find the first/next matching item'))
|
||||
ac = QAction(parent)
|
||||
parent.addAction(ac)
|
||||
parent.keyboard.register_shortcut('tag browser find button',
|
||||
_('Find button'), default_keys=(),
|
||||
_('Find in Tag browser'), default_keys=(),
|
||||
action=ac, group=_('Tag browser'))
|
||||
ac.triggered.connect(self.search_button.click)
|
||||
|
||||
self.toggle_search_button = b = QToolButton(self)
|
||||
le = self.item_search.lineEdit()
|
||||
le.addAction(QIcon(I('window-close.png')), le.LeadingPosition).triggered.connect(self.toggle_search_button.click)
|
||||
le.addAction(QIcon(I('window-close.png')), le.LeadingPosition).triggered.connect(self.close_find_box)
|
||||
b.setCursor(Qt.PointingHandCursor)
|
||||
b.setIcon(QIcon(I('search.png')))
|
||||
b.setCheckable(True)
|
||||
@ -409,6 +423,11 @@ class TagBrowserBar(QWidget): # {{{
|
||||
b.toggled.connect(self.update_searchbar_state)
|
||||
self.update_searchbar_state()
|
||||
|
||||
def close_find_box(self):
|
||||
self.item_search.setCurrentIndex(0)
|
||||
self.item_search.setCurrentText('')
|
||||
self.toggle_search_button.click()
|
||||
|
||||
def set_focus_to_find_box(self):
|
||||
self.toggle_search_button.setChecked(True)
|
||||
self.item_search.setFocus()
|
||||
@ -489,7 +508,7 @@ class TagBrowserWidget(QWidget): # {{{
|
||||
ac = QAction(parent)
|
||||
parent.addAction(ac)
|
||||
parent.keyboard.register_shortcut('tag browser alter',
|
||||
_('Alter Tag browser'), default_keys=(),
|
||||
_('Change Tag browser'), default_keys=(),
|
||||
action=ac, group=_('Tag browser'))
|
||||
ac.triggered.connect(l.showMenu)
|
||||
|
||||
|
@ -12,8 +12,7 @@ import re, string, traceback
|
||||
|
||||
from calibre import prints
|
||||
from calibre.constants import DEBUG
|
||||
from calibre.utils.formatter_functions import formatter_functions, compile_user_function
|
||||
from calibre.utils.config import tweaks
|
||||
from calibre.utils.formatter_functions import formatter_functions
|
||||
|
||||
|
||||
class _Parser(object):
|
||||
@ -174,6 +173,7 @@ class _Parser(object):
|
||||
else:
|
||||
self.error(_('expression is not function or constant'))
|
||||
|
||||
|
||||
class TemplateFormatter(string.Formatter):
|
||||
'''
|
||||
Provides a format function that substitutes '' for any missing value
|
||||
|
@ -1635,6 +1635,7 @@ class UserFunction(FormatterUserFunction):
|
||||
cls = locals_['UserFunction'](name, doc, arg_count, eval_func)
|
||||
return cls
|
||||
|
||||
|
||||
def compile_user_template_functions(funcs):
|
||||
compiled_funcs = {}
|
||||
for func in funcs:
|
||||
@ -1653,6 +1654,7 @@ def compile_user_template_functions(funcs):
|
||||
traceback.print_exc()
|
||||
return compiled_funcs
|
||||
|
||||
|
||||
def load_user_template_functions(library_uuid, funcs, precompiled_user_functions=None):
|
||||
unload_user_template_functions(library_uuid)
|
||||
if precompiled_user_functions:
|
||||
@ -1661,5 +1663,6 @@ def load_user_template_functions(library_uuid, funcs, precompiled_user_functions
|
||||
compiled_funcs = compile_user_template_functions(funcs)
|
||||
formatter_functions().register_functions(library_uuid, compiled_funcs.values())
|
||||
|
||||
|
||||
def unload_user_template_functions(library_uuid):
|
||||
formatter_functions().unregister_functions(library_uuid)
|
||||
|
Loading…
x
Reference in New Issue
Block a user