mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add a new function booksize() to the template language to get the value of the size column in calibre. Fix ratings in templates being multiplied by 2
This commit is contained in:
commit
cd93a31066
@ -592,7 +592,7 @@ class Metadata(object):
|
|||||||
elif datatype == 'bool':
|
elif datatype == 'bool':
|
||||||
res = _('Yes') if res else _('No')
|
res = _('Yes') if res else _('No')
|
||||||
elif datatype == 'rating':
|
elif datatype == 'rating':
|
||||||
res = res/2
|
res = res/2.0
|
||||||
return (name, unicode(res), orig_res, cmeta)
|
return (name, unicode(res), orig_res, cmeta)
|
||||||
|
|
||||||
# convert top-level ids into their value
|
# convert top-level ids into their value
|
||||||
@ -625,6 +625,8 @@ class Metadata(object):
|
|||||||
res = res + ' [%s]'%self.format_series_index()
|
res = res + ' [%s]'%self.format_series_index()
|
||||||
elif datatype == 'datetime':
|
elif datatype == 'datetime':
|
||||||
res = format_date(res, fmeta['display'].get('date_format','dd MMM yyyy'))
|
res = format_date(res, fmeta['display'].get('date_format','dd MMM yyyy'))
|
||||||
|
elif datatype == 'rating':
|
||||||
|
res = res/2.0
|
||||||
return (name, unicode(res), orig_res, fmeta)
|
return (name, unicode(res), orig_res, fmeta)
|
||||||
|
|
||||||
return (None, None, None, None)
|
return (None, None, None, None)
|
||||||
|
@ -7,7 +7,7 @@ import os, traceback, Queue, time, cStringIO, re, sys
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, \
|
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, \
|
||||||
Qt, pyqtSignal, QDialog
|
Qt, pyqtSignal, QDialog, QObject
|
||||||
|
|
||||||
from calibre.customize.ui import available_input_formats, available_output_formats, \
|
from calibre.customize.ui import available_input_formats, available_output_formats, \
|
||||||
device_plugins
|
device_plugins
|
||||||
@ -587,18 +587,26 @@ class DeviceMenu(QMenu): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
class DeviceMixin(object): # {{{
|
class DeviceSignals(QObject):
|
||||||
|
|
||||||
#: This signal is emitted once, after metadata is downloaded from the
|
#: This signal is emitted once, after metadata is downloaded from the
|
||||||
#: connected device.
|
#: connected device.
|
||||||
#: The sequence: gui.device_manager.is_device_connected will become True,
|
#: The sequence: gui.device_manager.is_device_connected will become True,
|
||||||
|
#: and the device_connection_changed signal will be emitted,
|
||||||
#: then sometime later gui.device_metadata_available will be signaled.
|
#: then sometime later gui.device_metadata_available will be signaled.
|
||||||
#: This does not mean that there are no more jobs running. Automatic metadata
|
#: This does not mean that there are no more jobs running. Automatic metadata
|
||||||
#: management might have kicked off a sync_booklists to write new metadata onto
|
#: management might have kicked off a sync_booklists to write new metadata onto
|
||||||
#: the device, and that job might still be running when the signal is emitted.
|
#: the device, and that job might still be running when the signal is emitted.
|
||||||
device_metadata_available = pyqtSignal()
|
device_metadata_available = pyqtSignal()
|
||||||
|
|
||||||
|
#: This signal is emitted once when the device is detected and once when
|
||||||
|
#: it is disconnected. If the parameter is True, then it is a connection,
|
||||||
|
#: otherwise a disconnection.
|
||||||
device_connection_changed = pyqtSignal(object)
|
device_connection_changed = pyqtSignal(object)
|
||||||
|
|
||||||
|
device_signals = DeviceSignals()
|
||||||
|
|
||||||
|
class DeviceMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.device_error_dialog = error_dialog(self, _('Error'),
|
self.device_error_dialog = error_dialog(self, _('Error'),
|
||||||
_('Error communicating with device'), ' ')
|
_('Error communicating with device'), ' ')
|
||||||
@ -745,7 +753,7 @@ class DeviceMixin(object): # {{{
|
|||||||
self.location_manager.update_devices()
|
self.location_manager.update_devices()
|
||||||
self.library_view.set_device_connected(self.device_connected)
|
self.library_view.set_device_connected(self.device_connected)
|
||||||
self.refresh_ondevice()
|
self.refresh_ondevice()
|
||||||
self.device_connection_changed.emit(connected)
|
device_signals.device_connection_changed.emit(connected)
|
||||||
|
|
||||||
def info_read(self, job):
|
def info_read(self, job):
|
||||||
'''
|
'''
|
||||||
@ -784,7 +792,7 @@ class DeviceMixin(object): # {{{
|
|||||||
self.sync_news()
|
self.sync_news()
|
||||||
self.sync_catalogs()
|
self.sync_catalogs()
|
||||||
self.refresh_ondevice()
|
self.refresh_ondevice()
|
||||||
self.device_metadata_available.emit()
|
device_signals.device_metadata_available.emit()
|
||||||
|
|
||||||
def refresh_ondevice(self, reset_only = False):
|
def refresh_ondevice(self, reset_only = False):
|
||||||
'''
|
'''
|
||||||
|
@ -156,8 +156,6 @@ class SearchBar(QWidget): # {{{
|
|||||||
x = ComboBoxWithHelp(self)
|
x = ComboBoxWithHelp(self)
|
||||||
x.setMaximumSize(QSize(150, 16777215))
|
x.setMaximumSize(QSize(150, 16777215))
|
||||||
x.setObjectName("search_restriction")
|
x.setObjectName("search_restriction")
|
||||||
x.setToolTip(_('Books display will be restricted to those matching the '
|
|
||||||
'selected saved search'))
|
|
||||||
l.addWidget(x)
|
l.addWidget(x)
|
||||||
parent.search_restriction = x
|
parent.search_restriction = x
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ class SearchRestrictionMixin(object):
|
|||||||
self.search_restriction.setMinimumContentsLength(10)
|
self.search_restriction.setMinimumContentsLength(10)
|
||||||
self.search_restriction.setStatusTip(self.search_restriction.toolTip())
|
self.search_restriction.setStatusTip(self.search_restriction.toolTip())
|
||||||
self.search_count.setText(_("(all books)"))
|
self.search_count.setText(_("(all books)"))
|
||||||
|
self.search_restriction_tooltip = \
|
||||||
|
_('Books display will be restricted to those matching a '
|
||||||
|
'selected saved search')
|
||||||
|
self.search_restriction.setToolTip(self.search_restriction_tooltip)
|
||||||
|
|
||||||
def apply_named_search_restriction(self, name):
|
def apply_named_search_restriction(self, name):
|
||||||
if not name:
|
if not name:
|
||||||
@ -30,29 +34,38 @@ class SearchRestrictionMixin(object):
|
|||||||
self.apply_search_restriction(r)
|
self.apply_search_restriction(r)
|
||||||
|
|
||||||
def apply_text_search_restriction(self, search):
|
def apply_text_search_restriction(self, search):
|
||||||
|
search = unicode(search)
|
||||||
if not search:
|
if not search:
|
||||||
self.search_restriction.setItemText(1, _('*Current search'))
|
|
||||||
self.search_restriction.setCurrentIndex(0)
|
self.search_restriction.setCurrentIndex(0)
|
||||||
else:
|
else:
|
||||||
self.search_restriction.setCurrentIndex(1)
|
s = '*' + search
|
||||||
self.search_restriction.setItemText(1, search)
|
if self.search_restriction.count() > 1:
|
||||||
|
txt = unicode(self.search_restriction.itemText(2))
|
||||||
|
if txt.startswith('*'):
|
||||||
|
self.search_restriction.setItemText(2, s)
|
||||||
|
else:
|
||||||
|
self.search_restriction.insertItem(2, s)
|
||||||
|
else:
|
||||||
|
self.search_restriction.insertItem(2, s)
|
||||||
|
self.search_restriction.setCurrentIndex(2)
|
||||||
|
self.search_restriction.setToolTip('<p>' +
|
||||||
|
self.search_restriction_tooltip +
|
||||||
|
_(' or the search ') + "'" + search + "'</p>")
|
||||||
self._apply_search_restriction(search)
|
self._apply_search_restriction(search)
|
||||||
|
|
||||||
def apply_search_restriction(self, i):
|
def apply_search_restriction(self, i):
|
||||||
self.search_restriction.setItemText(1, _('*Current search'))
|
|
||||||
if i == 1:
|
if i == 1:
|
||||||
restriction = unicode(self.search.currentText())
|
self.apply_text_search_restriction(unicode(self.search.currentText()))
|
||||||
if not restriction:
|
elif i == 2 and unicode(self.search_restriction.currentText()).startswith('*'):
|
||||||
self.search_restriction.setCurrentIndex(0)
|
self.apply_text_search_restriction(
|
||||||
else:
|
unicode(self.search_restriction.currentText())[1:])
|
||||||
self.search_restriction.setItemText(1, restriction)
|
|
||||||
else:
|
else:
|
||||||
r = unicode(self.search_restriction.currentText())
|
r = unicode(self.search_restriction.currentText())
|
||||||
if r is not None and r != '':
|
if r is not None and r != '':
|
||||||
restriction = 'search:"%s"'%(r)
|
restriction = 'search:"%s"'%(r)
|
||||||
else:
|
else:
|
||||||
restriction = ''
|
restriction = ''
|
||||||
self._apply_search_restriction(restriction)
|
self._apply_search_restriction(restriction)
|
||||||
|
|
||||||
def _apply_search_restriction(self, restriction):
|
def _apply_search_restriction(self, restriction):
|
||||||
self.saved_search.clear()
|
self.saved_search.clear()
|
||||||
|
@ -853,6 +853,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
mi.pubdate = row[fm['pubdate']]
|
mi.pubdate = row[fm['pubdate']]
|
||||||
mi.uuid = row[fm['uuid']]
|
mi.uuid = row[fm['uuid']]
|
||||||
mi.title_sort = row[fm['sort']]
|
mi.title_sort = row[fm['sort']]
|
||||||
|
mi.book_size = row[fm['size']]
|
||||||
mi.last_modified = row[fm['last_modified']]
|
mi.last_modified = row[fm['last_modified']]
|
||||||
formats = row[fm['formats']]
|
formats = row[fm['formats']]
|
||||||
if not formats:
|
if not formats:
|
||||||
@ -1378,13 +1379,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
for (cat, dex, mult, is_comp) in md:
|
for (cat, dex, mult, is_comp) in md:
|
||||||
if not book[dex]:
|
if not book[dex]:
|
||||||
continue
|
continue
|
||||||
|
tid_cat = tids[cat]
|
||||||
|
tcats_cat = tcategories[cat]
|
||||||
if not mult:
|
if not mult:
|
||||||
val = book[dex]
|
val = book[dex]
|
||||||
if is_comp:
|
if is_comp:
|
||||||
item = tcategories[cat].get(val, None)
|
item = tcats_cat.get(val, None)
|
||||||
if not item:
|
if not item:
|
||||||
item = tag_class(val, val)
|
item = tag_class(val, val)
|
||||||
tcategories[cat][val] = item
|
tcats_cat[val] = item
|
||||||
item.c += 1
|
item.c += 1
|
||||||
item.id = val
|
item.id = val
|
||||||
if rating > 0:
|
if rating > 0:
|
||||||
@ -1392,11 +1395,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
item.rc += 1
|
item.rc += 1
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
(item_id, sort_val) = tids[cat][val] # let exceptions fly
|
(item_id, sort_val) = tid_cat[val] # let exceptions fly
|
||||||
item = tcategories[cat].get(val, None)
|
item = tcats_cat.get(val, None)
|
||||||
if not item:
|
if not item:
|
||||||
item = tag_class(val, sort_val)
|
item = tag_class(val, sort_val)
|
||||||
tcategories[cat][val] = item
|
tcats_cat[val] = item
|
||||||
item.c += 1
|
item.c += 1
|
||||||
item.id_set.add(book[0])
|
item.id_set.add(book[0])
|
||||||
item.id = item_id
|
item.id = item_id
|
||||||
@ -1410,21 +1413,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
if is_comp:
|
if is_comp:
|
||||||
vals = [v.strip() for v in vals if v.strip()]
|
vals = [v.strip() for v in vals if v.strip()]
|
||||||
for val in vals:
|
for val in vals:
|
||||||
if val not in tids:
|
if val not in tid_cat:
|
||||||
tids[cat][val] = (val, val)
|
tid_cat[val] = (val, val)
|
||||||
item = tcategories[cat].get(val, None)
|
|
||||||
if not item:
|
|
||||||
item = tag_class(val, val)
|
|
||||||
tcategories[cat][val] = item
|
|
||||||
item.c += 1
|
|
||||||
item.id = val
|
|
||||||
for val in vals:
|
for val in vals:
|
||||||
try:
|
try:
|
||||||
(item_id, sort_val) = tids[cat][val] # let exceptions fly
|
(item_id, sort_val) = tid_cat[val] # let exceptions fly
|
||||||
item = tcategories[cat].get(val, None)
|
item = tcats_cat.get(val, None)
|
||||||
if not item:
|
if not item:
|
||||||
item = tag_class(val, sort_val)
|
item = tag_class(val, sort_val)
|
||||||
tcategories[cat][val] = item
|
tcats_cat[val] = item
|
||||||
item.c += 1
|
item.c += 1
|
||||||
item.id_set.add(book[0])
|
item.id_set.add(book[0])
|
||||||
item.id = item_id
|
item.id = item_id
|
||||||
|
@ -198,7 +198,6 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
|||||||
for key in custom_metadata:
|
for key in custom_metadata:
|
||||||
if key in format_args:
|
if key in format_args:
|
||||||
cm = custom_metadata[key]
|
cm = custom_metadata[key]
|
||||||
## TODO: NEWMETA: should ratings be divided by 2? The standard rating isn't...
|
|
||||||
if cm['datatype'] == 'series':
|
if cm['datatype'] == 'series':
|
||||||
format_args[key] = title_sort(format_args[key], order=tsorder)
|
format_args[key] = title_sort(format_args[key], order=tsorder)
|
||||||
if key+'_index' in format_args:
|
if key+'_index' in format_args:
|
||||||
|
@ -230,6 +230,7 @@ The following functions are available in addition to those described in single-f
|
|||||||
|
|
||||||
* ``add(x, y)`` -- returns x + y. Throws an exception if either x or y are not numbers.
|
* ``add(x, y)`` -- returns x + y. Throws an exception if either x or y are not numbers.
|
||||||
* ``assign(id, val)`` -- assigns val to id, then returns val. id must be an identifier, not an expression
|
* ``assign(id, val)`` -- assigns val to id, then returns val. id must be an identifier, not an expression
|
||||||
|
* ``booksize()`` -- returns the value of the |app| 'size' field. Returns '' if there are no formats.
|
||||||
* ``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``.
|
* ``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``.
|
||||||
* ``divide(x, y)`` -- returns x / y. Throws an exception if either x or y are not numbers.
|
* ``divide(x, y)`` -- returns x / y. Throws an exception if either x or y are not numbers.
|
||||||
* ``field(name)`` -- returns the metadata field named by ``name``.
|
* ``field(name)`` -- returns the metadata field named by ``name``.
|
||||||
|
@ -549,8 +549,22 @@ class BuiltinCapitalize(BuiltinFormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||||
return capitalize(val)
|
return capitalize(val)
|
||||||
|
|
||||||
|
class BuiltinBooksize(BuiltinFormatterFunction):
|
||||||
|
name = 'booksize'
|
||||||
|
arg_count = 0
|
||||||
|
doc = _('booksize() -- return value of the field capitalized')
|
||||||
|
|
||||||
|
def evaluate(self, formatter, kwargs, mi, locals):
|
||||||
|
if mi.book_size is not None:
|
||||||
|
try:
|
||||||
|
return str(mi.book_size)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return ''
|
||||||
|
|
||||||
builtin_add = BuiltinAdd()
|
builtin_add = BuiltinAdd()
|
||||||
builtin_assign = BuiltinAssign()
|
builtin_assign = BuiltinAssign()
|
||||||
|
builtin_booksize = BuiltinBooksize()
|
||||||
builtin_capitalize = BuiltinCapitalize()
|
builtin_capitalize = BuiltinCapitalize()
|
||||||
builtin_cmp = BuiltinCmp()
|
builtin_cmp = BuiltinCmp()
|
||||||
builtin_contains = BuiltinContains()
|
builtin_contains = BuiltinContains()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user