Merge branch 'master' of https://github.com/cbhaley/calibre into master

This commit is contained in:
Kovid Goyal 2020-09-22 07:49:46 +05:30
commit c28a031735
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 42 additions and 3 deletions

View File

@ -254,6 +254,7 @@ The following functions are available in addition to those described in single-f
returns "yes" if the yes/no field ``"#bool"`` is either undefined (neither True nor False) or True. More than one of ``is_undefined``, ``is_false``, or ``is_true`` can be set to 1. This function is usually used by the ``test()`` or ``is_empty()`` functions.
* ``ceiling(x)`` -- returns the smallest integer greater than or equal to x. Throws an exception if x is not a number.
* ``cmp(x, y, lt, eq, gt)`` -- compares x and y after converting both to numbers. Returns ``lt`` if x < y. Returns ``eq`` if x == y. Otherwise returns ``gt``.
* ``connected_device_name(storage_location)`` -- if a device is connected then return the device name, otherwise return the empty string. Each storage location on a device can have a different name. The location names are 'main', 'carda' and 'cardb'. This function works only in the GUI.
* ``current_library_name()`` -- return the last name on the path to the current calibre library. This function can be called in template program mode using the template ``{:'current_library_name()'}``.
* ``current_library_path()`` -- return the path to the current calibre library. This function can be called in template program mode using the template ``{:'current_library_path()'}``.
* ``days_between(date1, date2)`` -- return the number of days between ``date1`` and ``date2``. The number is positive if ``date1`` is greater than ``date2``, otherwise negative. If either ``date1`` or ``date2`` are not dates, the function returns the empty string.

View File

@ -10,7 +10,7 @@ from threading import Thread, Event
from PyQt5.Qt import (
QMenu, QAction, QActionGroup, QIcon, Qt, pyqtSignal, QDialog,
QObject, QVBoxLayout, QDialogButtonBox, QCursor, QCoreApplication,
QApplication, QEventLoop)
QApplication, QEventLoop, QTimer)
from calibre.customize.ui import (available_input_formats, available_output_formats,
device_plugins, disabled_device_plugins)
@ -1100,7 +1100,12 @@ class DeviceMixin(object): # {{{
# Empty any device view information
for v in dviews:
v.set_database([])
self.refresh_ondevice()
# Use a singleShot timer to ensure that the job event queue has
# emptied before the ondevice column is removed from the booklist.
# This deals with race conditions when repainting the booklist
# causing incorrect evaluation of the connected_device_name
# formatter function
QTimer.singleShot(0, self.refresh_ondevice)
device_signals.device_connection_changed.emit(connected)
def info_read(self, job):

View File

@ -1668,6 +1668,39 @@ class BuiltinAuthorSorts(BuiltinFormatterFunction):
return val_sep.join(n for n in names)
class BuiltinConnectedDeviceName(BuiltinFormatterFunction):
name = 'connected_device_name'
arg_count = 1
category = 'Get values from metadata'
__doc__ = doc = _("connected_device_name(storage_location) -- if a device is "
"connected then return the device name, otherwise return "
"the empty string. Each storage location on a device can "
"have a different name. The location names are 'main', "
"'carda' and 'cardb'. This function works only in the GUI.")
def evaluate(self, formatter, kwargs, mi, locals, storage_location):
if hasattr(mi, '_proxy_metadata'):
# Do the import here so that we don't entangle the GUI when using
# command line functions
from calibre.gui2.ui import get_gui
info = get_gui().device_manager.get_current_device_information()
if info is None:
return ''
try:
if storage_location not in {'main', 'carda', 'cardb'}:
raise ValueError(
_('connected_device_name: invalid storage location "{0}"'
.format(storage_location)))
info = info['info'][4]
if storage_location not in info:
return ''
return info[storage_location]['device_name']
except:
traceback.print_exc()
raise
return _('This function can be used only in the GUI')
class BuiltinCheckYesNo(BuiltinFormatterFunction):
name = 'check_yes_no'
arg_count = 4
@ -1754,7 +1787,7 @@ _formatter_builtins = [
BuiltinAdd(), BuiltinAnd(), BuiltinApproximateFormats(), BuiltinAssign(),
BuiltinAuthorLinks(), BuiltinAuthorSorts(), BuiltinBooksize(),
BuiltinCapitalize(), BuiltinCheckYesNo(), BuiltinCeiling(),
BuiltinCmp(), BuiltinContains(),
BuiltinCmp(), BuiltinConnectedDeviceName(), BuiltinContains(),
BuiltinCount(), BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(),
BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(),
BuiltinField(), BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), BuiltinFloor(),