From ec30cb26f8ad770d8f92b3246b2959ef0dfe8292 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Dec 2012 12:11:38 +0100 Subject: [PATCH 1/2] Add an "Entire row" option to column coloring --- src/calibre/gui2/library/models.py | 36 +++++++++++++++++++++++- src/calibre/gui2/preferences/coloring.py | 15 ++++++---- src/calibre/library/coloring.py | 3 ++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index b2b2597434..81c4ed1a1a 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -27,6 +27,7 @@ from calibre import strftime, isbytestring from calibre.constants import filesystem_encoding, DEBUG from calibre.gui2.library import DEFAULT_SORT from calibre.utils.localization import calibre_langcode_to_name +from calibre.library.coloring import color_row_key def human_readable(size, precision=1): """ Convert a size in bytes into megabytes """ @@ -84,6 +85,7 @@ class BooksModel(QAbstractTableModel): # {{{ self.headers = {} self.alignment_map = {} self.color_cache = defaultdict(dict) + self.color_row_fmt_cache = None self.buffer_size = buffer self.metadata_backup = None self.bool_yes_icon = QIcon(I('ok.png')) @@ -169,12 +171,14 @@ class BooksModel(QAbstractTableModel): # {{{ def refresh_ids(self, ids, current_row=-1): self.color_cache = defaultdict(dict) + self.color_row_fmt_cache = None rows = self.db.refresh_ids(ids) if rows: self.refresh_rows(rows, current_row=current_row) def refresh_rows(self, rows, current_row=-1): self.color_cache = defaultdict(dict) + self.color_row_fmt_cache = None for row in rows: if row == current_row: self.new_bookdisplay_data.emit( @@ -206,6 +210,7 @@ class BooksModel(QAbstractTableModel): # {{{ def count_changed(self, *args): self.color_cache = defaultdict(dict) + self.color_row_fmt_cache = None self.count_changed_signal.emit(self.db.count()) def row_indices(self, index): @@ -337,6 +342,7 @@ class BooksModel(QAbstractTableModel): # {{{ def reset(self): self.color_cache = defaultdict(dict) + self.color_row_fmt_cache = None QAbstractTableModel.reset(self) def resort(self, reset=True): @@ -728,10 +734,15 @@ class BooksModel(QAbstractTableModel): # {{{ elif role == Qt.ForegroundRole: key = self.column_map[col] mi = None + id_ = self.id(index) + + if self.color_row_fmt_cache is None: + d = dict(self.db.prefs['column_color_rules']) + self.color_row_fmt_cache = d.get(color_row_key, '') + for k, fmt in self.db.prefs['column_color_rules']: if k != key: continue - id_ = self.id(index) if id_ in self.color_cache: if key in self.color_cache[id_]: return self.color_cache[id_][key] @@ -747,6 +758,7 @@ class BooksModel(QAbstractTableModel): # {{{ return color except: continue + if self.is_custom_column(key) and \ self.custom_columns[key]['datatype'] == 'enumeration': cc = self.custom_columns[self.column_map[col]]['display'] @@ -760,6 +772,28 @@ class BooksModel(QAbstractTableModel): # {{{ return QVariant(color) except: pass + + # There is cloned code below. Done for performance. + if self.color_row_fmt_cache: + key = color_row_key + if id_ in self.color_cache: + if key in self.color_cache[id_]: + return self.color_cache[id_][key] + try: + if mi is None: + mi = self.db.get_metadata(id_, index_is_id=True) + color = self.formatter.safe_format(self.color_row_fmt_cache, + mi, '', mi) + if color in self.colors: + color = QColor(color) + if color.isValid(): + color = QVariant(color) + self.color_cache[id_][key] = color + return color + except: + pass + self.color_cache[id_][key] = None + return NONE elif role == Qt.DecorationRole: if self.column_to_dc_decorator_map[col] is not None: diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index 831e658b59..6830f15904 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -19,7 +19,7 @@ from calibre.gui2 import error_dialog from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.gui2.metadata.single_download import RichTextDelegate from calibre.library.coloring import (Rule, conditionable_columns, - displayable_columns, rule_from_template) + displayable_columns, rule_from_template, color_row_key) from calibre.utils.localization import lang_map from calibre.utils.icu import lower @@ -315,9 +315,13 @@ class RuleEditor(QDialog): # {{{ for key in sorted( displayable_columns(fm), key=sort_key): - name = fm[key]['name'] - if name: - self.column_box.addItem(key, key) + if key == color_row_key: + name = _('Entire row') + self.column_box.addItem(name, key) + else: + name = fm[key]['name'] + if name: + self.column_box.addItem(key, key) self.column_box.setCurrentIndex(0) self.color_box.addItems(QColor.colorNames()) @@ -427,7 +431,8 @@ class RulesModel(QAbstractListModel): # {{{ col, rule = self.rules[row] except: return None - + if col == color_row_key: + col = _('Entire row') if role == Qt.DisplayRole: return self.rule_to_html(col, rule) if role == Qt.UserRole: diff --git a/src/calibre/library/coloring.py b/src/calibre/library/coloring.py index 4847a48c7d..9c6724cf69 100644 --- a/src/calibre/library/coloring.py +++ b/src/calibre/library/coloring.py @@ -11,6 +11,8 @@ __docformat__ = 'restructuredtext en' import binascii, re, json from textwrap import dedent +color_row_key = '*row' + class Rule(object): # {{{ SIGNATURE = '# BasicColorRule():' @@ -205,6 +207,7 @@ def conditionable_columns(fm): yield key def displayable_columns(fm): + yield (color_row_key) for key in fm.displayable_field_keys(): if key not in ('sort', 'author_sort', 'comments', 'formats', 'identifiers', 'path'): From a787c986f815ad7a1e97f31a138f72e94655ab56 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Dec 2012 13:41:18 +0100 Subject: [PATCH 2/2] ... --- src/calibre/gui2/preferences/coloring.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index 6830f15904..1190bac978 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -62,6 +62,8 @@ class ConditionEditor(QWidget): # {{{ ), } + all_columns_string = _('All Columns') + for x in ('float', 'rating', 'datetime'): ACTION_MAP[x] = ACTION_MAP['int'] @@ -316,7 +318,7 @@ class RuleEditor(QDialog): # {{{ displayable_columns(fm), key=sort_key): if key == color_row_key: - name = _('Entire row') + name = self.all_columns_string self.column_box.addItem(name, key) else: name = fm[key]['name'] @@ -432,7 +434,7 @@ class RulesModel(QAbstractListModel): # {{{ except: return None if col == color_row_key: - col = _('Entire row') + col = self.all_columns_string if role == Qt.DisplayRole: return self.rule_to_html(col, rule) if role == Qt.UserRole: