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:
Kovid Goyal 2011-04-19 08:39:31 -06:00
commit cd93a31066
8 changed files with 67 additions and 35 deletions

View File

@ -592,7 +592,7 @@ class Metadata(object):
elif datatype == 'bool':
res = _('Yes') if res else _('No')
elif datatype == 'rating':
res = res/2
res = res/2.0
return (name, unicode(res), orig_res, cmeta)
# convert top-level ids into their value
@ -625,6 +625,8 @@ class Metadata(object):
res = res + ' [%s]'%self.format_series_index()
elif datatype == 'datetime':
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 (None, None, None, None)

View File

@ -7,7 +7,7 @@ import os, traceback, Queue, time, cStringIO, re, sys
from threading import Thread
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, \
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
#: connected device.
#: 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.
#: 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
#: the device, and that job might still be running when the signal is emitted.
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_signals = DeviceSignals()
class DeviceMixin(object): # {{{
def __init__(self):
self.device_error_dialog = error_dialog(self, _('Error'),
_('Error communicating with device'), ' ')
@ -745,7 +753,7 @@ class DeviceMixin(object): # {{{
self.location_manager.update_devices()
self.library_view.set_device_connected(self.device_connected)
self.refresh_ondevice()
self.device_connection_changed.emit(connected)
device_signals.device_connection_changed.emit(connected)
def info_read(self, job):
'''
@ -784,7 +792,7 @@ class DeviceMixin(object): # {{{
self.sync_news()
self.sync_catalogs()
self.refresh_ondevice()
self.device_metadata_available.emit()
device_signals.device_metadata_available.emit()
def refresh_ondevice(self, reset_only = False):
'''

View File

@ -156,8 +156,6 @@ class SearchBar(QWidget): # {{{
x = ComboBoxWithHelp(self)
x.setMaximumSize(QSize(150, 16777215))
x.setObjectName("search_restriction")
x.setToolTip(_('Books display will be restricted to those matching the '
'selected saved search'))
l.addWidget(x)
parent.search_restriction = x

View File

@ -17,6 +17,10 @@ class SearchRestrictionMixin(object):
self.search_restriction.setMinimumContentsLength(10)
self.search_restriction.setStatusTip(self.search_restriction.toolTip())
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):
if not name:
@ -30,29 +34,38 @@ class SearchRestrictionMixin(object):
self.apply_search_restriction(r)
def apply_text_search_restriction(self, search):
search = unicode(search)
if not search:
self.search_restriction.setItemText(1, _('*Current search'))
self.search_restriction.setCurrentIndex(0)
else:
self.search_restriction.setCurrentIndex(1)
self.search_restriction.setItemText(1, search)
s = '*' + 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)
def apply_search_restriction(self, i):
self.search_restriction.setItemText(1, _('*Current search'))
if i == 1:
restriction = unicode(self.search.currentText())
if not restriction:
self.search_restriction.setCurrentIndex(0)
else:
self.search_restriction.setItemText(1, restriction)
self.apply_text_search_restriction(unicode(self.search.currentText()))
elif i == 2 and unicode(self.search_restriction.currentText()).startswith('*'):
self.apply_text_search_restriction(
unicode(self.search_restriction.currentText())[1:])
else:
r = unicode(self.search_restriction.currentText())
if r is not None and r != '':
restriction = 'search:"%s"'%(r)
else:
restriction = ''
self._apply_search_restriction(restriction)
self._apply_search_restriction(restriction)
def _apply_search_restriction(self, restriction):
self.saved_search.clear()

View File

@ -853,6 +853,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
mi.pubdate = row[fm['pubdate']]
mi.uuid = row[fm['uuid']]
mi.title_sort = row[fm['sort']]
mi.book_size = row[fm['size']]
mi.last_modified = row[fm['last_modified']]
formats = row[fm['formats']]
if not formats:
@ -1378,13 +1379,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
for (cat, dex, mult, is_comp) in md:
if not book[dex]:
continue
tid_cat = tids[cat]
tcats_cat = tcategories[cat]
if not mult:
val = book[dex]
if is_comp:
item = tcategories[cat].get(val, None)
item = tcats_cat.get(val, None)
if not item:
item = tag_class(val, val)
tcategories[cat][val] = item
tcats_cat[val] = item
item.c += 1
item.id = val
if rating > 0:
@ -1392,11 +1395,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
item.rc += 1
continue
try:
(item_id, sort_val) = tids[cat][val] # let exceptions fly
item = tcategories[cat].get(val, None)
(item_id, sort_val) = tid_cat[val] # let exceptions fly
item = tcats_cat.get(val, None)
if not item:
item = tag_class(val, sort_val)
tcategories[cat][val] = item
tcats_cat[val] = item
item.c += 1
item.id_set.add(book[0])
item.id = item_id
@ -1410,21 +1413,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if is_comp:
vals = [v.strip() for v in vals if v.strip()]
for val in vals:
if val not in tids:
tids[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
if val not in tid_cat:
tid_cat[val] = (val, val)
for val in vals:
try:
(item_id, sort_val) = tids[cat][val] # let exceptions fly
item = tcategories[cat].get(val, None)
(item_id, sort_val) = tid_cat[val] # let exceptions fly
item = tcats_cat.get(val, None)
if not item:
item = tag_class(val, sort_val)
tcategories[cat][val] = item
tcats_cat[val] = item
item.c += 1
item.id_set.add(book[0])
item.id = item_id

View File

@ -198,7 +198,6 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
for key in custom_metadata:
if key in format_args:
cm = custom_metadata[key]
## TODO: NEWMETA: should ratings be divided by 2? The standard rating isn't...
if cm['datatype'] == 'series':
format_args[key] = title_sort(format_args[key], order=tsorder)
if key+'_index' in format_args:

View File

@ -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.
* ``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``.
* ``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``.

View File

@ -549,8 +549,22 @@ class BuiltinCapitalize(BuiltinFormatterFunction):
def evaluate(self, formatter, kwargs, mi, locals, 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_assign = BuiltinAssign()
builtin_booksize = BuiltinBooksize()
builtin_capitalize = BuiltinCapitalize()
builtin_cmp = BuiltinCmp()
builtin_contains = BuiltinContains()