diff --git a/manual/template_lang.rst b/manual/template_lang.rst index d7d15da146..6ebb766437 100644 --- a/manual/template_lang.rst +++ b/manual/template_lang.rst @@ -252,6 +252,7 @@ The following functions are available in addition to those described in single-f * ``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. + * ``connected_device_uuid(storage_location)`` -- if a device is connected then return the device uuid (unique id), otherwise return the empty string. Each storage location on a device has a different uuid. 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. diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 82bb19bb95..720a563f40 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -1722,6 +1722,40 @@ class BuiltinConnectedDeviceName(BuiltinFormatterFunction): return _('This function can be used only in the GUI') +class BuiltinConnectedDeviceUUID(BuiltinFormatterFunction): + name = 'connected_device_uuid' + arg_count = 1 + category = 'Get values from metadata' + __doc__ = doc = _("connected_device_uuid(storage_location) -- if a device is " + "connected then return the device uuid (unique id), " + "otherwise return the empty string. Each storage location " + "on a device has a different uuid. 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_store_uuid'] + 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 @@ -1847,7 +1881,7 @@ _formatter_builtins = [ BuiltinAssign(), BuiltinAuthorLinks(), BuiltinAuthorSorts(), BuiltinBooksize(), BuiltinCapitalize(), BuiltinCheckYesNo(), BuiltinCeiling(), - BuiltinCmp(), BuiltinConnectedDeviceName(), BuiltinContains(), + BuiltinCmp(), BuiltinConnectedDeviceName(), BuiltinConnectedDeviceUUID(), BuiltinContains(), BuiltinCount(), BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(), BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(), BuiltinField(), BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), BuiltinFloor(),