From 6c26b9debc72060cfc10f1239d96311c1691ed08 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 29 May 2011 10:04:34 +0100
Subject: [PATCH 1/9] Add the ondevice() function to the template language
---
src/calibre/library/database2.py | 1 +
src/calibre/manual/template_lang.rst | 3 ++-
src/calibre/utils/formatter_functions.py | 18 +++++++++++++++++-
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index 819ac2cd24..df465c919e 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -860,6 +860,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
mi.uuid = row[fm['uuid']]
mi.title_sort = row[fm['sort']]
mi.book_size = row[fm['size']]
+ mi.ondevice_col= row[fm['ondevice']]
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 059376565d..28c9855ce4 100644
--- a/src/calibre/manual/template_lang.rst
+++ b/src/calibre/manual/template_lang.rst
@@ -255,6 +255,7 @@ The following functions are available in addition to those described in single-f
* ``not(value)`` -- returns the string "1" if the value is empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want.
* ``merge_lists(list1, list2, separator)`` -- return a list made by merging the items in list1 and list2, removing duplicate items using a case-insensitive compare. If items differ in case, the one in list1 is used. The items in list1 and list2 are separated by separator, as are the items in the returned list.
* ``multiply(x, y)`` -- returns x * y. Throws an exception if either x or y are not numbers.
+ * ``ondevice()`` -- return the string "Yes" if ondevice is set, otherwise return the empty string
* ``or(value, value, ...)`` -- returns the string "1" if any value is not empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want.
* ``print(a, b, ...)`` -- prints the arguments to standard output. Unless you start calibre from the command line (``calibre-debug -g``), the output will go to a black hole.
* ``raw_field(name)`` -- returns the metadata field named by name without applying any formatting.
@@ -277,7 +278,7 @@ Function classification summary:
* Relational: ``cmp`` , ``strcmp`` for strings
* String case changes: ``lowercase``, ``uppercase``, ``titlecase``, ``capitalize``
* String manipulation: ``re``, ``shorten``, ``substr``
- * Other: ``assign``, ``booksize``, ``print``, ``format_date``,
+ * Other: ``assign``, ``booksize``, ``format_date``, ``ondevice`` ``print``
.. _general_mode:
diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py
index 2f15d5d592..761da2c8e2 100644
--- a/src/calibre/utils/formatter_functions.py
+++ b/src/calibre/utils/formatter_functions.py
@@ -568,7 +568,7 @@ class BuiltinCapitalize(BuiltinFormatterFunction):
class BuiltinBooksize(BuiltinFormatterFunction):
name = 'booksize'
arg_count = 0
- doc = _('booksize() -- return value of the field capitalized')
+ doc = _('booksize() -- return value of the size field')
def evaluate(self, formatter, kwargs, mi, locals):
if mi.book_size is not None:
@@ -578,6 +578,21 @@ class BuiltinBooksize(BuiltinFormatterFunction):
pass
return ''
+class BuiltinOndevice(BuiltinFormatterFunction):
+ name = 'ondevice'
+ arg_count = 0
+ doc = _('ondevice() -- return Yes if ondevice is set, otherwise return '
+ 'the empty string')
+
+ def evaluate(self, formatter, kwargs, mi, locals):
+ print mi.ondevice_col
+ if mi.ondevice_col:
+ try:
+ return _('Yes')
+ except:
+ pass
+ return ''
+
class BuiltinFirstNonEmpty(BuiltinFormatterFunction):
name = 'first_non_empty'
arg_count = -1
@@ -687,6 +702,7 @@ builtin_lowercase = BuiltinLowercase()
builtin_merge_lists = BuiltinMergeLists()
builtin_multiply = BuiltinMultiply()
builtin_not = BuiltinNot()
+builtin_ondevice = BuiltinOndevice()
builtin_or = BuiltinOr()
builtin_print = BuiltinPrint()
builtin_raw_field = BuiltinRaw_field()
From faffa55cf1299cc1beaf257f0aea765db2d37fb5 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 29 May 2011 10:05:47 +0100
Subject: [PATCH 2/9] take out print statement
---
src/calibre/utils/formatter_functions.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py
index 761da2c8e2..bf597d5b9c 100644
--- a/src/calibre/utils/formatter_functions.py
+++ b/src/calibre/utils/formatter_functions.py
@@ -585,7 +585,6 @@ class BuiltinOndevice(BuiltinFormatterFunction):
'the empty string')
def evaluate(self, formatter, kwargs, mi, locals):
- print mi.ondevice_col
if mi.ondevice_col:
try:
return _('Yes')
From 393cfe78cdca8f96b4e85d40e612087af86076f0 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 29 May 2011 11:30:04 +0100
Subject: [PATCH 3/9] Improvements to editing templates and formatter exception
reporting. Largest improvement is adding a value preview box to the template
editor.
---
src/calibre/ebooks/metadata/book/base.py | 39 +++++++--------
src/calibre/gui2/dialogs/template_dialog.py | 10 +++-
src/calibre/gui2/dialogs/template_dialog.ui | 50 +++++++++++++------
.../gui2/dialogs/template_line_editor.py | 6 ++-
src/calibre/gui2/library/delegates.py | 3 +-
src/calibre/gui2/preferences/look_feel.py | 10 ++++
src/calibre/utils/formatter.py | 9 ++--
src/calibre/utils/formatter_functions.py | 21 +++-----
8 files changed, 92 insertions(+), 56 deletions(-)
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index 5dc3f25dfb..179a96e578 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -41,27 +41,24 @@ field_metadata = FieldMetadata()
class SafeFormat(TemplateFormatter):
- def get_value(self, key, args, kwargs):
- try:
- key = key.lower()
- if key != 'title_sort' and key not in TOP_LEVEL_IDENTIFIERS:
- key = field_metadata.search_term_to_field_key(key)
- b = self.book.get_user_metadata(key, False)
- if b and b['datatype'] == 'int' and self.book.get(key, 0) == 0:
- v = ''
- elif b and b['datatype'] == 'float' and self.book.get(key, 0.0) == 0.0:
- v = ''
- else:
- v = self.book.format_field(key, series_with_index=False)[1]
- if v is None:
- return ''
- if v == '':
- return ''
- return v
- except:
- if DEBUG:
- traceback.print_exc()
- return key
+ def get_value(self, orig_key, args, kwargs):
+ key = orig_key.lower()
+ if key != 'title_sort' and key not in TOP_LEVEL_IDENTIFIERS:
+ key = field_metadata.search_term_to_field_key(key)
+ if key is None or key not in self.book.all_field_keys():
+ raise ValueError(_('Value: unknown field ') + orig_key)
+ b = self.book.get_user_metadata(key, False)
+ if b and b['datatype'] == 'int' and self.book.get(key, 0) == 0:
+ v = ''
+ elif b and b['datatype'] == 'float' and self.book.get(key, 0.0) == 0.0:
+ v = ''
+ else:
+ v = self.book.format_field(key, series_with_index=False)[1]
+ if v is None:
+ return ''
+ if v == '':
+ return ''
+ return v
composite_formatter = SafeFormat()
diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py
index ca55bb0e66..083dacbf00 100644
--- a/src/calibre/gui2/dialogs/template_dialog.py
+++ b/src/calibre/gui2/dialogs/template_dialog.py
@@ -11,6 +11,7 @@ from PyQt4.Qt import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter,
from calibre.gui2.dialogs.template_dialog_ui import Ui_TemplateDialog
from calibre.utils.formatter_functions import formatter_functions
+from calibre.ebooks.metadata.book.base import composite_formatter
class ParenPosition:
@@ -194,10 +195,13 @@ class TemplateHighlighter(QSyntaxHighlighter):
class TemplateDialog(QDialog, Ui_TemplateDialog):
- def __init__(self, parent, text):
+ def __init__(self, parent, text, mi):
QDialog.__init__(self, parent)
Ui_TemplateDialog.__init__(self)
self.setupUi(self)
+
+ self.mi = mi
+
# Remove help icon on title bar
icon = self.windowIcon()
self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
@@ -233,12 +237,16 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.function.addItems(func_names)
self.function.setCurrentIndex(0)
self.function.currentIndexChanged[str].connect(self.function_changed)
+ self.textbox_changed()
def textbox_changed(self):
cur_text = unicode(self.textbox.toPlainText())
if self.last_text != cur_text:
self.last_text = cur_text
self.highlighter.regenerate_paren_positions()
+ self.template_value.setText(
+ composite_formatter.safe_format(cur_text, self.mi,
+ _('EXCEPTION: '), self.mi))
def text_cursor_changed(self):
cursor = self.textbox.textCursor()
diff --git a/src/calibre/gui2/dialogs/template_dialog.ui b/src/calibre/gui2/dialogs/template_dialog.ui
index dd8fb7bd88..d36cbbd3d4 100644
--- a/src/calibre/gui2/dialogs/template_dialog.ui
+++ b/src/calibre/gui2/dialogs/template_dialog.ui
@@ -23,19 +23,39 @@
' +
+ _('You can enter more than one tag per box, separated by commas. '
+ 'The comparison ignores letter case.
'
+ 'A tag value can be a regular expression. '
+ 'When using regular expressions, note that the wizard '
+ 'puts anchors (^ and $) around the expression, so you '
+ 'must ensure your expression matches from the beginning '
+ 'to the end of the tag.
'
+ 'Regular expression examples:') + '' +
+ _('
.*
matches any tag. No empty tags are '
+ 'checked, so you don\'t need to worry about empty stringsA.*
matches any tag beginning with A.*mystery.*
matches any tag containing '
+ 'the word "mystery"
' + + _('At least one of the two color boxes must have a value. Leave ' + 'one color box empty if you want the template to use the next ' + 'line in this wizard. If both boxes are filled in, the rest of ' + 'the lines in this wizard will be ignored.') + '
') + l.addWidget(c, 0, 1, 1, 1) + c = QLabel(_('Color if tag not found')) + c.setToolTip('' + + _('This box is usually filled in only on the last test. If it is ' + 'filled in before the last test, then the color for tag found box ' + 'must be empty or all the rest of the tests will be ignored.') + '
') + l.addWidget(c, 0, 2, 1, 1) self.tagboxes = [] self.colorboxes = [] + self.nfcolorboxes = [] self.colors = [unicode(s) for s in list(QColor.colorNames())] self.colors.insert(0, '') for i in range(0, 10): @@ -85,15 +113,25 @@ class TagWizard(QDialog): cb.addItems(self.colors) self.colorboxes.append(cb) l.addWidget(cb, i+1, 1, 1, 1) + cb = QComboBox(self) + cb.addItems(self.colors) + self.nfcolorboxes.append(cb) + l.addWidget(cb, i+1, 2, 1, 1) if txt: lines = txt.split('\n')[3:] i = 0 for line in lines: if line.startswith('#'): - t,c = line[1:].split(':|:') + vals = line[1:].split(':|:') + if len(vals) == 2: + t, c = vals + nc = '' + else: + t,c,nc = vals try: self.colorboxes[i].setCurrentIndex(self.colorboxes[i].findText(c)) + self.nfcolorboxes[i].setCurrentIndex(self.nfcolorboxes[i].findText(nc)) self.tagboxes[i].setText(t) except: pass @@ -109,28 +147,35 @@ class TagWizard(QDialog): res = ("program:\n#tag wizard -- do not directly edit\n" " t = field('tags');\n first_non_empty(\n") lines = [] - for tb, cb in zip(self.tagboxes, self.colorboxes): + for tb, cb, nfcb in zip(self.tagboxes, self.colorboxes, self.nfcolorboxes): tags = [t.strip() for t in unicode(tb.text()).split(',') if t.strip()] tags = '$|^'.join(tags) c = unicode(cb.currentText()).strip() - if not tags or not c: + nfc = unicode(nfcb.currentText()).strip() + if not tags or not (c or nfc): continue if c not in self.colors: error_dialog(self, _('Invalid color'), _('The color {0} is not valid').format(c), show=True, show_copy_button=False) return False - lines.append(" in_list(t, ',', '^{0}$', '{1}', '')".format(tags, c)) + if nfc not in self.colors: + error_dialog(self, _('Invalid color'), + _('The color {0} is not valid').format(nfc), + show=True, show_copy_button=False) + return False + lines.append(" in_list(t, ',', '^{0}$', '{1}', '{2}')".format(tags, c, nfc)) res += ',\n'.join(lines) res += ')\n' self.template = res res = '' - for tb, cb in zip(self.tagboxes, self.colorboxes): + for tb, cb, nfcb in zip(self.tagboxes, self.colorboxes, self.nfcolorboxes): t = unicode(tb.text()).strip() if t.endswith(','): t = t[:-1] c = unicode(cb.currentText()).strip() + nfc = unicode(nfcb.currentText()).strip() if t and c: - res += '#' + t + ':|:' + c + '\n' + res += '#' + t + ':|:' + c + ':|:' + nfc + '\n' self.template += res self.accept() From 67d570de1c99867e69796cac4710a409bfaf34c2 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 29 May 2011 13:39:35 +0100 Subject: [PATCH 5/9] Permit empty keys in templates. Simplifies using functions that don't require a value --- src/calibre/ebooks/metadata/book/base.py | 2 ++ src/calibre/library/save_to_disk.py | 2 ++ src/calibre/utils/formatter.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py index 179a96e578..f98bebe1dc 100644 --- a/src/calibre/ebooks/metadata/book/base.py +++ b/src/calibre/ebooks/metadata/book/base.py @@ -42,6 +42,8 @@ field_metadata = FieldMetadata() class SafeFormat(TemplateFormatter): def get_value(self, orig_key, args, kwargs): + if not orig_key: + return '' key = orig_key.lower() if key != 'title_sort' and key not in TOP_LEVEL_IDENTIFIERS: key = field_metadata.search_term_to_field_key(key) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index dc83b44c01..5f49833564 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -134,6 +134,8 @@ class SafeFormat(TemplateFormatter): ''' def get_value(self, key, args, kwargs): + if key == '': + return '' try: key = key.lower() try: diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py index 695355330e..ebf47db854 100644 --- a/src/calibre/utils/formatter.py +++ b/src/calibre/utils/formatter.py @@ -342,6 +342,8 @@ class EvalFormatter(TemplateFormatter): A template formatter that uses a simple dict instead of an mi instance ''' def get_value(self, key, args, kwargs): + if key == '': + return '' key = key.lower() return kwargs.get(key, _('No such variable ') + key) From 0d57a3fb18f03574a242789cce9189e33aa2e54e Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 29 May 2011 14:09:01 +0100 Subject: [PATCH 6/9] Correct some problems with setting the ondevice column values when the device is disconnected. --- src/calibre/gui2/device.py | 3 ++- src/calibre/gui2/library/models.py | 2 +- src/calibre/utils/formatter_functions.py | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 3977a6bca1..dd9d7aaa50 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -1294,7 +1294,8 @@ class DeviceMixin(object): # {{{ self.book_db_uuid_path_map = None return - if not hasattr(self, 'db_book_uuid_cache'): + if not self.device_manager.is_device_connected or \ + not hasattr(self, 'db_book_uuid_cache'): return loc if self.book_db_id_cache is None: diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 554b104c34..793f2d353b 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -125,7 +125,7 @@ class BooksModel(QAbstractTableModel): # {{{ def refresh_ondevice(self): self.db.refresh_ondevice() - self.resort() + self.refresh(reset=False) self.research() def set_book_on_device_func(self, func): diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index d7b6e63f5e..76faf04941 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -579,10 +579,7 @@ class BuiltinOndevice(BuiltinFormatterFunction): def evaluate(self, formatter, kwargs, mi, locals): if mi.ondevice_col: - try: - return _('Yes') - except: - pass + return _('Yes') return '' class BuiltinFirstNonEmpty(BuiltinFormatterFunction): From 322e6d9ac44e9304cccfedda1d69a654f9805673 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 29 May 2011 15:09:56 +0100 Subject: [PATCH 7/9] Add an RE box to the color tags wizard. Add the necessary function to the template language. Fix problem with passing mi to the template editor. --- src/calibre/ebooks/metadata/book/base.py | 2 +- .../gui2/dialogs/template_line_editor.py | 67 +++++++++++++------ src/calibre/gui2/preferences/look_feel.py | 3 +- src/calibre/utils/formatter_functions.py | 22 +++++- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py index f98bebe1dc..3e2201f6a4 100644 --- a/src/calibre/ebooks/metadata/book/base.py +++ b/src/calibre/ebooks/metadata/book/base.py @@ -47,7 +47,7 @@ class SafeFormat(TemplateFormatter): key = orig_key.lower() if key != 'title_sort' and key not in TOP_LEVEL_IDENTIFIERS: key = field_metadata.search_term_to_field_key(key) - if key is None or key not in self.book.all_field_keys(): + if key is None or (self.book and key not in self.book.all_field_keys()): raise ValueError(_('Value: unknown field ') + orig_key) b = self.book.get_user_metadata(key, False) if b and b['datatype'] == 'int' and self.book.get(key, 0) == 0: diff --git a/src/calibre/gui2/dialogs/template_line_editor.py b/src/calibre/gui2/dialogs/template_line_editor.py index d466cecc55..3d199b156c 100644 --- a/src/calibre/gui2/dialogs/template_line_editor.py +++ b/src/calibre/gui2/dialogs/template_line_editor.py @@ -5,7 +5,7 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal' +
_('You can enter more than one tag per box, separated by commas. '
'The comparison ignores letter case.
'
- 'A tag value can be a regular expression. '
- 'When using regular expressions, note that the wizard '
+ 'A tag value can be a regular expression. Check the box to turn '
+ 'them on. When using regular expressions, note that the wizard '
'puts anchors (^ and $) around the expression, so you '
'must ensure your expression matches from the beginning '
'to the end of the tag.
'
@@ -85,22 +85,29 @@ class TagWizard(QDialog):
'
.*mystery.*
matches any tag containing '
'the word "mystery"' + + _('Check this box if the tag box contains regular expressions') + '
') + l.addWidget(c, 0, 1, 1, 1) + c = QLabel(_('Color if tag found')) c.setToolTip('' + _('At least one of the two color boxes must have a value. Leave ' 'one color box empty if you want the template to use the next ' 'line in this wizard. If both boxes are filled in, the rest of ' 'the lines in this wizard will be ignored.') + '
') - l.addWidget(c, 0, 1, 1, 1) + l.addWidget(c, 0, 2, 1, 1) c = QLabel(_('Color if tag not found')) c.setToolTip('' + _('This box is usually filled in only on the last test. If it is ' 'filled in before the last test, then the color for tag found box ' 'must be empty or all the rest of the tests will be ignored.') + '
') - l.addWidget(c, 0, 2, 1, 1) + l.addWidget(c, 0, 3, 1, 1) self.tagboxes = [] self.colorboxes = [] self.nfcolorboxes = [] + self.reboxes = [] self.colors = [unicode(s) for s in list(QColor.colorNames())] self.colors.insert(0, '') for i in range(0, 10): @@ -109,14 +116,20 @@ class TagWizard(QDialog): tb.update_items_cache(self.tags) self.tagboxes.append(tb) l.addWidget(tb, i+1, 0, 1, 1) - cb = QComboBox(self) - cb.addItems(self.colors) - self.colorboxes.append(cb) - l.addWidget(cb, i+1, 1, 1, 1) - cb = QComboBox(self) - cb.addItems(self.colors) - self.nfcolorboxes.append(cb) - l.addWidget(cb, i+1, 2, 1, 1) + + w = QCheckBox(self) + self.reboxes.append(w) + l.addWidget(w, i+1, 1, 1, 1) + + w = QComboBox(self) + w.addItems(self.colors) + self.colorboxes.append(w) + l.addWidget(w, i+1, 2, 1, 1) + + w = QComboBox(self) + w.addItems(self.colors) + self.nfcolorboxes.append(w) + l.addWidget(w, i+1, 3, 1, 1) if txt: lines = txt.split('\n')[3:] @@ -127,18 +140,20 @@ class TagWizard(QDialog): if len(vals) == 2: t, c = vals nc = '' + re = False else: - t,c,nc = vals + t,c,nc,re = vals try: self.colorboxes[i].setCurrentIndex(self.colorboxes[i].findText(c)) self.nfcolorboxes[i].setCurrentIndex(self.nfcolorboxes[i].findText(nc)) self.tagboxes[i].setText(t) + self.reboxes[i].setChecked(re == '2') except: pass i += 1 bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel, parent=self) - l.addWidget(bb, 100, 1, 1, 1) + l.addWidget(bb, 100, 2, 1, 2) bb.accepted.connect(self.accepted) bb.rejected.connect(self.reject) self.template = '' @@ -147,11 +162,16 @@ class TagWizard(QDialog): res = ("program:\n#tag wizard -- do not directly edit\n" " t = field('tags');\n first_non_empty(\n") lines = [] - for tb, cb, nfcb in zip(self.tagboxes, self.colorboxes, self.nfcolorboxes): + for tb, cb, nfcb, reb in zip(self.tagboxes, self.colorboxes, + self.nfcolorboxes, self.reboxes): tags = [t.strip() for t in unicode(tb.text()).split(',') if t.strip()] - tags = '$|^'.join(tags) c = unicode(cb.currentText()).strip() nfc = unicode(nfcb.currentText()).strip() + re = reb.checkState() + if re == 2: + tags = '$|^'.join(tags) + else: + tags = ','.join(tags) if not tags or not (c or nfc): continue if c not in self.colors: @@ -164,18 +184,25 @@ class TagWizard(QDialog): _('The color {0} is not valid').format(nfc), show=True, show_copy_button=False) return False - lines.append(" in_list(t, ',', '^{0}$', '{1}', '{2}')".format(tags, c, nfc)) + if re == 2: + lines.append(" in_list(t, ',', '^{0}$', '{1}', '{2}')".\ + format(tags, c, nfc)) + else: + lines.append(" str_in_list(t, ',', '{0}', '{1}', '{2}')".\ + format(tags, c, nfc)) res += ',\n'.join(lines) res += ')\n' self.template = res res = '' - for tb, cb, nfcb in zip(self.tagboxes, self.colorboxes, self.nfcolorboxes): + for tb, cb, nfcb, reb in zip(self.tagboxes, self.colorboxes, + self.nfcolorboxes, self.reboxes): t = unicode(tb.text()).strip() if t.endswith(','): t = t[:-1] c = unicode(cb.currentText()).strip() nfc = unicode(nfcb.currentText()).strip() + re = unicode(reb.checkState()) if t and c: - res += '#' + t + ':|:' + c + ':|:' + nfc + '\n' + res += '#' + t + ':|:' + c + ':|:' + nfc + ':|:' + re + '\n' self.template += res self.accept() diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index fcdd56fd5f..37e4588b9b 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -209,8 +209,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): mi=None try: idx = gui.library_view.currentIndex().row() - if idx: - mi = db.get_metadata(idx, index_is_id=False) + mi = db.get_metadata(idx, index_is_id=False) except: pass diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 76faf04941..7d5dbe3e0e 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -8,7 +8,7 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal