From 3e0c43283d54a36c2574801070171cee33d974af Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Mon, 18 Apr 2011 21:43:10 +0100 Subject: [PATCH 1/6] Change author_sort_copy_method default from invert to comma. --- resources/default_tweaks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index c4c951f980..091aa9a34d 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -48,7 +48,7 @@ authors_completer_append_separator = False # When this tweak is changed, the author_sort values stored with each author # must be recomputed by right-clicking on an author in the left-hand tags pane, # selecting 'manage authors', and pressing 'Recalculate all author sort values'. -author_sort_copy_method = 'invert' +author_sort_copy_method = 'comma' #: Use author sort in Tag Browser # Set which author field to display in the tags pane (the list of authors, From 5312b49d85132787bc4f18d91fa7a8230561e298 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Apr 2011 08:59:53 +0100 Subject: [PATCH 2/6] Divide ratings by 2 when used in a template. --- src/calibre/ebooks/metadata/book/base.py | 2 ++ src/calibre/library/save_to_disk.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py index 167ae52fa3..57c267319f 100644 --- a/src/calibre/ebooks/metadata/book/base.py +++ b/src/calibre/ebooks/metadata/book/base.py @@ -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 return (name, unicode(res), orig_res, fmeta) return (None, None, None, None) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index 3c57af40a8..42e6c8b156 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -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: From 1e1b530113636d344c59e2c93fdabc3ca974a5cf Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Apr 2011 09:46:43 +0100 Subject: [PATCH 3/6] Add the ability to get the calibre field 'size' using a formatter function booksize() --- src/calibre/library/database2.py | 1 + src/calibre/manual/template_lang.rst | 1 + src/calibre/utils/formatter_functions.py | 14 ++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index bdcefd13a2..d585c60aef 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -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: diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index cdb8df2e2b..a77f0d1697 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -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``. diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 7957bd0749..aa8e4fb3a3 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -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() From d95d6eca67f7fc6f6b06cf2ab8d70477ffec9048 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Apr 2011 10:07:10 +0100 Subject: [PATCH 4/6] Improve performance of get_categories. --- src/calibre/library/database2.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index d585c60aef..bc0a8235e4 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1379,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: @@ -1393,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 @@ -1411,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 From b4dda2792357736ec155412f46facce563afb274 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Apr 2011 13:42:09 +0100 Subject: [PATCH 5/6] Very strange change to prevent calibre from dieing when device_metadata_available or device_connection_changed is emitted. --- src/calibre/gui2/device.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 99cb5848ba..d00aa031f5 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -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,8 +587,7 @@ 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, @@ -599,6 +598,10 @@ class DeviceMixin(object): # {{{ device_metadata_available = pyqtSignal() 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 +748,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 +787,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): ''' From d7f17e9a1975af262e2c894bfa0815cd04fdb9c1 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 19 Apr 2011 14:28:59 +0100 Subject: [PATCH 6/6] Improvements to using the current search as a restriction --- src/calibre/gui2/layout.py | 2 -- src/calibre/gui2/search_restriction_mixin.py | 33 ++++++++++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index c72b074463..7250103615 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -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 diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py index 8ef02b34b0..ffebc9e131 100644 --- a/src/calibre/gui2/search_restriction_mixin.py +++ b/src/calibre/gui2/search_restriction_mixin.py @@ -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('
' + + self.search_restriction_tooltip + + _(' or the search ') + "'" + search + "'
") 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()