diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py
index a3caa82e4b..50ce72686a 100644
--- a/src/calibre/gui2/book_details.py
+++ b/src/calibre/gui2/book_details.py
@@ -44,7 +44,9 @@ def render_rows(data):
key = key.decode(preferred_encoding, 'replace')
if isinstance(txt, str):
txt = txt.decode(preferred_encoding, 'replace')
- if '' not in txt:
+ if key.endswith(u':html'):
+ key = key[:-5]
+ elif '' not in txt:
txt = prepare_string_for_xml(txt)
if 'id' in data:
if key == _('Path'):
diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py
index ca9243e51e..bf66ea7235 100644
--- a/src/calibre/gui2/custom_column_widgets.py
+++ b/src/calibre/gui2/custom_column_widgets.py
@@ -15,6 +15,7 @@ from PyQt4.Qt import QComboBox, QLabel, QSpinBox, QDoubleSpinBox, QDateEdit, \
from calibre.utils.date import qt_to_dt, now
from calibre.gui2.widgets import TagsLineEdit, EnComboBox
+from calibre.gui2.comments_editor import Editor as CommentsEditor
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
from calibre.utils.config import tweaks
from calibre.utils.icu import sort_key
@@ -186,9 +187,9 @@ class Comments(Base):
self._box = QGroupBox(parent)
self._box.setTitle('&'+self.col_metadata['name'])
self._layout = QVBoxLayout()
- self._tb = QPlainTextEdit(self._box)
+ self._tb = CommentsEditor(self._box)
self._tb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
- self._tb.setTabChangesFocus(True)
+ #self._tb.setTabChangesFocus(True)
self._layout.addWidget(self._tb)
self._box.setLayout(self._layout)
self.widgets = [self._box]
@@ -196,10 +197,10 @@ class Comments(Base):
def setter(self, val):
if val is None:
val = ''
- self._tb.setPlainText(val)
+ self._tb.html = val
def getter(self):
- val = unicode(self._tb.toPlainText()).strip()
+ val = unicode(self._tb.html).strip()
if not val:
val = None
return val
diff --git a/src/calibre/gui2/dialogs/comments_dialog.py b/src/calibre/gui2/dialogs/comments_dialog.py
index 5d53448b94..51b29fa989 100644
--- a/src/calibre/gui2/dialogs/comments_dialog.py
+++ b/src/calibre/gui2/dialogs/comments_dialog.py
@@ -5,6 +5,7 @@ __license__ = 'GPL v3'
from PyQt4.Qt import Qt, QDialog, QDialogButtonBox
from calibre.gui2.dialogs.comments_dialog_ui import Ui_CommentsDialog
+from calibre.library.comments import comments_to_html
class CommentsDialog(QDialog, Ui_CommentsDialog):
@@ -18,8 +19,8 @@ class CommentsDialog(QDialog, Ui_CommentsDialog):
self.setWindowIcon(icon)
if text is not None:
- self.textbox.setPlainText(text)
- self.textbox.setTabChangesFocus(True)
+ self.textbox.html = comments_to_html(text)
+ # self.textbox.setTabChangesFocus(True)
self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK'))
self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel'))
diff --git a/src/calibre/gui2/dialogs/comments_dialog.ui b/src/calibre/gui2/dialogs/comments_dialog.ui
index dccfa48652..9c6e6cb861 100644
--- a/src/calibre/gui2/dialogs/comments_dialog.ui
+++ b/src/calibre/gui2/dialogs/comments_dialog.ui
@@ -19,22 +19,29 @@
Edit Comments
-
- -
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
-
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+ Editor
+ QWidget
+ calibre/gui2/comments_editor.h
+
+
diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py
new file mode 100644
index 0000000000..aaa4e2bb9a
--- /dev/null
+++ b/src/calibre/gui2/dialogs/template_dialog.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
+__docformat__ = 'restructuredtext en'
+__license__ = 'GPL v3'
+
+from PyQt4.Qt import Qt, QDialog, QDialogButtonBox
+from calibre.gui2.dialogs.template_dialog_ui import Ui_TemplateDialog
+
+class TemplateDialog(QDialog, Ui_TemplateDialog):
+
+ def __init__(self, parent, text):
+ QDialog.__init__(self, parent)
+ Ui_TemplateDialog.__init__(self)
+ self.setupUi(self)
+ # Remove help icon on title bar
+ icon = self.windowIcon()
+ self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
+ self.setWindowIcon(icon)
+
+ if text is not None:
+ self.textbox.setPlainText(text)
+ self.textbox.setTabChangesFocus(True)
+ self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK'))
+ self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel'))
+
diff --git a/src/calibre/gui2/dialogs/template_dialog.ui b/src/calibre/gui2/dialogs/template_dialog.ui
new file mode 100644
index 0000000000..3eacace2c5
--- /dev/null
+++ b/src/calibre/gui2/dialogs/template_dialog.ui
@@ -0,0 +1,73 @@
+
+
+ TemplateDialog
+
+
+
+ 0
+ 0
+ 336
+ 235
+
+
+
+
+ 0
+ 0
+
+
+
+ Edit Comments
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ TemplateDialog
+ accept()
+
+
+ 229
+ 211
+
+
+ 157
+ 234
+
+
+
+
+ buttonBox
+ rejected()
+ TemplateDialog
+ reject()
+
+
+ 297
+ 217
+
+
+ 286
+ 234
+
+
+
+
+
diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py
index fe7e7d55ba..2ae6cf2936 100644
--- a/src/calibre/gui2/library/delegates.py
+++ b/src/calibre/gui2/library/delegates.py
@@ -13,7 +13,7 @@ from PyQt4.Qt import QColor, Qt, QModelIndex, QSize, \
QPen, QStyle, QPainter, QStyleOptionViewItemV4, \
QIcon, QDoubleSpinBox, QVariant, QSpinBox, \
QStyledItemDelegate, QCompleter, \
- QComboBox
+ QComboBox, QTextDocument
from calibre.gui2 import UNDEFINED_QDATE, error_dialog
from calibre.gui2.widgets import EnLineEdit, TagsLineEdit
@@ -22,6 +22,8 @@ from calibre.utils.config import tweaks
from calibre.utils.formatter import validation_formatter
from calibre.utils.icu import sort_key
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
+from calibre.gui2.dialogs.template_dialog import TemplateDialog
+
class RatingDelegate(QStyledItemDelegate): # {{{
COLOR = QColor("blue")
@@ -294,6 +296,20 @@ class CcCommentsDelegate(QStyledItemDelegate): # {{{
Delegate for comments data.
'''
+ def paint(self, painter, option, index):
+ document = QTextDocument()
+ value = index.data(Qt.DisplayRole)
+# if value.isValid() and not value.isNull():
+# QString text("This is highlighted.");
+ text = value.toString()
+ document.setHtml(text);
+ painter.save()
+ painter.setClipRect(option.rect)
+ painter.translate(option.rect.topLeft());
+ document.drawContents(painter);
+ painter.restore()
+# painter.translate(-option.rect.topLeft());
+
def createEditor(self, parent, option, index):
m = index.model()
col = m.column_map[index.column()]
@@ -301,11 +317,11 @@ class CcCommentsDelegate(QStyledItemDelegate): # {{{
editor = CommentsDialog(parent, text)
d = editor.exec_()
if d:
- m.setData(index, QVariant(editor.textbox.toPlainText()), Qt.EditRole)
+ m.setData(index, QVariant(editor.textbox.html), Qt.EditRole)
return None
def setModelData(self, editor, model, index):
- model.setData(index, QVariant(editor.textbox.toPlainText()), Qt.EditRole)
+ model.setData(index, QVariant(editor.textbox.html), Qt.EditRole)
# }}}
class CcBoolDelegate(QStyledItemDelegate): # {{{
@@ -351,7 +367,7 @@ class CcTemplateDelegate(QStyledItemDelegate): # {{{
def createEditor(self, parent, option, index):
m = index.model()
text = m.custom_columns[m.column_map[index.column()]]['display']['composite_template']
- editor = CommentsDialog(parent, text)
+ editor = TemplateDialog(parent, text)
editor.setWindowTitle(_("Edit template"))
editor.textbox.setTabChangesFocus(False)
editor.textbox.setTabStopWidth(20)
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 9da9a2f538..920753a77d 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -334,6 +334,8 @@ class BooksModel(QAbstractTableModel): # {{{
if key not in cf_to_display:
continue
name, val = mi.format_field(key)
+ if mi.metadata_for_field(key)['datatype'] == 'comments':
+ name += ':html'
if val:
data[name] = val
return data