diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py
index 60d4025ef9..174056ef80 100644
--- a/src/calibre/gui2/dialogs/template_dialog.py
+++ b/src/calibre/gui2/dialogs/template_dialog.py
@@ -3,8 +3,11 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__license__ = 'GPL v3'
+import json
+
from PyQt4.Qt import Qt, QDialog, QDialogButtonBox
from calibre.gui2.dialogs.template_dialog_ui import Ui_TemplateDialog
+from calibre.utils.formatter_functions import formatter_functions
class TemplateDialog(QDialog, Ui_TemplateDialog):
@@ -17,9 +20,41 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
self.setWindowIcon(icon)
+ self.textbox.setTabStopWidth(10)
+ self.source_code.setTabStopWidth(10)
+ self.documentation.setReadOnly(True)
+ self.source_code.setReadOnly(True)
+
if text is not None:
self.textbox.setPlainText(text)
- self.textbox.setTabStopWidth(50)
self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK'))
self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel'))
+ try:
+ with open(P('template-functions.json'), 'rb') as f:
+ self.builtin_source_dict = json.load(f, encoding='utf-8')
+ except:
+ self.builtin_source_dict = {}
+
+ self.funcs = formatter_functions.get_functions()
+ self.builtins = formatter_functions.get_builtins()
+
+ func_names = sorted(self.funcs)
+ self.function.clear()
+ self.function.addItem('')
+ self.function.addItems(func_names)
+ self.function.setCurrentIndex(0)
+ self.function.currentIndexChanged[str].connect(self.function_changed)
+
+ def function_changed(self, toWhat):
+ name = unicode(toWhat)
+ self.source_code.clear()
+ self.documentation.clear()
+ if name in self.funcs:
+ self.documentation.setPlainText(self.funcs[name].doc)
+ if name in self.builtins:
+ if name in self.builtin_source_dict:
+ self.source_code.setPlainText(self.builtin_source_dict[name])
+ else:
+ self.source_code.setPlainText(self.funcs[name].program_text)
+
diff --git a/src/calibre/gui2/dialogs/template_dialog.ui b/src/calibre/gui2/dialogs/template_dialog.ui
index a30d6ef273..dd8fb7bd88 100644
--- a/src/calibre/gui2/dialogs/template_dialog.ui
+++ b/src/calibre/gui2/dialogs/template_dialog.ui
@@ -6,8 +6,8 @@
0
0
- 500
- 235
+ 588
+ 546
@@ -19,21 +19,77 @@
Edit Comments
-
- -
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
-
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+ -
+
+
-
+
+
+ Function &name:
+
+
+ function
+
+
+
+ -
+
+
+ -
+
+
+ &Documentation:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ documentation
+
+
+
+ -
+
+
+ Python &code:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ source_code
+
+
+
+ -
+
+
+
+ 16777215
+ 75
+
+
+
+
+ -
+
+
+
+
+
diff --git a/src/calibre/gui2/preferences/template_functions.py b/src/calibre/gui2/preferences/template_functions.py
index 2e16b0f4c3..8ffd65b2b5 100644
--- a/src/calibre/gui2/preferences/template_functions.py
+++ b/src/calibre/gui2/preferences/template_functions.py
@@ -5,7 +5,7 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-import traceback
+import json, traceback
from calibre.gui2 import error_dialog
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
@@ -73,6 +73,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.textBrowser.setHtml(help_text)
def initialize(self):
+ try:
+ with open(P('template-functions.json'), 'rb') as f:
+ self.builtin_source_dict = json.load(f, encoding='utf-8')
+ except:
+ self.builtin_source_dict = {}
+
self.funcs = formatter_functions.get_functions()
self.builtins = formatter_functions.get_builtins()
@@ -179,8 +185,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
func = self.funcs[txt]
self.argument_count.setValue(func.arg_count)
self.documentation.setText(func.doc)
- self.program.setPlainText(func.program_text)
if txt in self.builtins:
+ if hasattr(func, 'program_text'):
+ self.program.setPlainText(func.program_text)
+ elif txt in self.builtin_source_dict:
+ self.program.setPlainText(self.builtin_source_dict[txt])
+ else:
+ self.program.setPlainText(_('function source code not available'))
self.documentation.setReadOnly(True)
self.argument_count.setReadOnly(True)
self.program.setReadOnly(True)
diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py
index 83f19b8711..622d6b8459 100644
--- a/src/calibre/library/sqlite.py
+++ b/src/calibre/library/sqlite.py
@@ -100,7 +100,7 @@ class AumSortedConcatenate(object):
keys = self.ans.keys()
l = len(keys)
if l == 0:
- return 'Unknown:::Unknown'
+ return None
if l == 1:
return self.ans[keys[0]]
return ':#:'.join([self.ans[v] for v in sorted(keys)])
diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py
index f025a0c9bf..2551b90788 100644
--- a/src/calibre/utils/date.py
+++ b/src/calibre/utils/date.py
@@ -148,6 +148,9 @@ def format_date(dt, format, assume_utc=False, as_utc=False):
if len(mo.group(0)) == 2: return '%02d'%(dt.year % 100)
return '%04d'%dt.year
+ if dt == UNDEFINED_DATE:
+ return ''
+
format = re.sub('d{1,4}', format_day, format)
format = re.sub('M{1,4}', format_month, format)
return re.sub('yyyy|yy', format_year, format)