From f209a7b079928c6b1516249a5ed0c1df3c36e627 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 28 May 2011 07:07:16 +0100 Subject: [PATCH 1/2] Add format strings to int and float custom columns --- src/calibre/ebooks/metadata/book/base.py | 6 +++ src/calibre/gui2/library/models.py | 10 ++++- .../gui2/preferences/create_custom_column.py | 9 +++++ .../gui2/preferences/create_custom_column.ui | 37 +++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py index ceb6751238..5dc3f25dfb 100644 --- a/src/calibre/ebooks/metadata/book/base.py +++ b/src/calibre/ebooks/metadata/book/base.py @@ -628,6 +628,12 @@ class Metadata(object): res = _('Yes') if res else _('No') elif datatype == 'rating': res = res/2.0 + elif datatype in ['int', 'float']: + try: + fmt = cmeta['display'].get('number_format', None) + res = fmt.format(res) + except: + pass return (name, unicode(res), orig_res, cmeta) # convert top-level ids into their value diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 86c5871193..554b104c34 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -623,7 +623,12 @@ class BooksModel(QAbstractTableModel): # {{{ return None return QVariant(text) - def number_type(r, idx=-1): + def number_type(r, idx=-1, fmt=None): + if fmt is not None: + try: + return QVariant(fmt.format(self.db.data[r][idx])) + except: + pass return QVariant(self.db.data[r][idx]) self.dc = { @@ -674,7 +679,8 @@ class BooksModel(QAbstractTableModel): # {{{ bool_cols_are_tristate= self.db.prefs.get('bools_are_tristate')) elif datatype in ('int', 'float'): - self.dc[col] = functools.partial(number_type, idx=idx) + fmt = self.custom_columns[col]['display'].get('number_format', None) + self.dc[col] = functools.partial(number_type, idx=idx, fmt=fmt) elif datatype == 'datetime': self.dc[col] = functools.partial(datetime_type, idx=idx) elif datatype == 'bool': diff --git a/src/calibre/gui2/preferences/create_custom_column.py b/src/calibre/gui2/preferences/create_custom_column.py index 3a245580dd..f3fe8f03a3 100644 --- a/src/calibre/gui2/preferences/create_custom_column.py +++ b/src/calibre/gui2/preferences/create_custom_column.py @@ -127,6 +127,9 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn): elif ct == 'enumeration': self.enum_box.setText(','.join(c['display'].get('enum_values', []))) self.enum_colors.setText(','.join(c['display'].get('enum_colors', []))) + elif ct in ['int', 'float']: + if c['display'].get('number_format', None): + self.number_format_box.setText(c['display'].get('number_format', '')) self.datatype_changed() if ct in ['text', 'composite', 'enumeration']: self.use_decorations.setChecked(c['display'].get('use_decorations', False)) @@ -171,6 +174,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn): col_type = None for x in ('box', 'default_label', 'label'): getattr(self, 'date_format_'+x).setVisible(col_type == 'datetime') + getattr(self, 'number_format_'+x).setVisible(col_type in ['int', 'float']) for x in ('box', 'default_label', 'label', 'sort_by', 'sort_by_label', 'make_category'): getattr(self, 'composite_'+x).setVisible(col_type in ['composite', '*composite']) @@ -267,6 +271,11 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn): display_dict = {'enum_values': l, 'enum_colors': c} elif col_type == 'text' and is_multiple: display_dict = {'is_names': self.is_names.isChecked()} + elif col_type in ['int', 'float']: + if unicode(self.number_format_box.text()).strip(): + display_dict = {'number_format':unicode(self.number_format_box.text()).strip()} + else: + display_dict = {'number_format': None} if col_type in ['text', 'composite', 'enumeration'] and not is_multiple: display_dict['use_decorations'] = self.use_decorations.checkState() diff --git a/src/calibre/gui2/preferences/create_custom_column.ui b/src/calibre/gui2/preferences/create_custom_column.ui index 2bdadd4b9d..02daae988f 100644 --- a/src/calibre/gui2/preferences/create_custom_column.ui +++ b/src/calibre/gui2/preferences/create_custom_column.ui @@ -171,6 +171,20 @@ Everything else will show nothing. + + + + + 0 + 0 + + + + <p>Use 0 (a zero) for the field name. Example: {0:0>5.2f} gives a 5-digit floating point number, 2 digits after the decimal point, with leading zeros + + + + @@ -181,6 +195,19 @@ Everything else will show nothing. + + + + <p>Example: ${0:,.2f} gives floating point number prefixed by a dollar sign, 2 digits after the decimal point, with thousands separated by commas + + + <p>Default: Not formatted. For format language details see <a href="http://docs.python.org/library/string.html#format-string-syntax">the python documentation</a> + + + true + + + @@ -193,6 +220,16 @@ Everything else will show nothing. + + + + Format for &numbers + + + number_format_box + + + From db78e9c45ef2d6cd98eaa02ee6b01a8a0f69e9d2 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 28 May 2011 12:27:49 +0100 Subject: [PATCH 2/2] Fix delegates to deal with formatted numbers --- src/calibre/gui2/library/delegates.py | 33 +++++++++++++++++++-------- src/calibre/gui2/library/views.py | 7 ++++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py index 50c411aaa4..6990a76b21 100644 --- a/src/calibre/gui2/library/delegates.py +++ b/src/calibre/gui2/library/delegates.py @@ -249,6 +249,23 @@ class CcDateDelegate(QStyledItemDelegate): # {{{ # }}} class CcTextDelegate(QStyledItemDelegate): # {{{ + ''' + Delegate for text data. + ''' + + def createEditor(self, parent, option, index): + m = index.model() + col = m.column_map[index.column()] + editor = MultiCompleteLineEdit(parent) + editor.set_separator(None) + complete_items = sorted(list(m.db.all_custom(label=m.db.field_metadata.key_to_label(col))), + key=sort_key) + editor.update_items_cache(complete_items) + return editor + +# }}} + +class CcNumberDelegate(QStyledItemDelegate): # {{{ ''' Delegate for text/int/float data. ''' @@ -256,25 +273,23 @@ class CcTextDelegate(QStyledItemDelegate): # {{{ def createEditor(self, parent, option, index): m = index.model() col = m.column_map[index.column()] - typ = m.custom_columns[col]['datatype'] - if typ == 'int': + if m.custom_columns[col]['datatype'] == 'int': editor = QSpinBox(parent) editor.setRange(-100, 100000000) editor.setSpecialValueText(_('Undefined')) editor.setSingleStep(1) - elif typ == 'float': + else: editor = QDoubleSpinBox(parent) editor.setSpecialValueText(_('Undefined')) editor.setRange(-100., 100000000) editor.setDecimals(2) - else: - editor = MultiCompleteLineEdit(parent) - editor.set_separator(None) - complete_items = sorted(list(m.db.all_custom(label=m.db.field_metadata.key_to_label(col))), - key=sort_key) - editor.update_items_cache(complete_items) return editor + def setEditorData(self, editor, index): + m = index.model() + val = m.db.data[index.row()][m.custom_columns[m.column_map[index.column()]]['rec_index']] + editor.setValue(val) + # }}} class CcEnumDelegate(QStyledItemDelegate): # {{{ diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 1cfb04921d..f59473851f 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -15,7 +15,7 @@ from PyQt4.Qt import QTableView, Qt, QAbstractItemView, QMenu, pyqtSignal, \ from calibre.gui2.library.delegates import RatingDelegate, PubDateDelegate, \ TextDelegate, DateDelegate, CompleteDelegate, CcTextDelegate, \ CcBoolDelegate, CcCommentsDelegate, CcDateDelegate, CcTemplateDelegate, \ - CcEnumDelegate + CcEnumDelegate, CcNumberDelegate from calibre.gui2.library.models import BooksModel, DeviceBooksModel from calibre.utils.config import tweaks, prefs from calibre.gui2 import error_dialog, gprefs @@ -89,6 +89,7 @@ class BooksView(QTableView): # {{{ self.cc_bool_delegate = CcBoolDelegate(self) self.cc_comments_delegate = CcCommentsDelegate(self) self.cc_template_delegate = CcTemplateDelegate(self) + self.cc_number_delegate = CcNumberDelegate(self) self.display_parent = parent self._model = modelcls(self) self.setModel(self._model) @@ -501,8 +502,10 @@ class BooksView(QTableView): # {{{ self.tags_delegate) else: self.setItemDelegateForColumn(cm.index(colhead), self.cc_text_delegate) - elif cc['datatype'] in ('series', 'int', 'float'): + elif cc['datatype'] == 'series': self.setItemDelegateForColumn(cm.index(colhead), self.cc_text_delegate) + elif cc['datatype'] in ('int', 'float'): + self.setItemDelegateForColumn(cm.index(colhead), self.cc_number_delegate) elif cc['datatype'] == 'bool': self.setItemDelegateForColumn(cm.index(colhead), self.cc_bool_delegate) elif cc['datatype'] == 'rating':