diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index b2b2597434..27fb56a7d2 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): @@ -727,17 +733,21 @@ class BooksModel(QAbstractTableModel): # {{{ return QVariant(QColor('lightgreen')) elif role == Qt.ForegroundRole: key = self.column_map[col] - mi = None - for k, fmt in self.db.prefs['column_color_rules']: - if k != key: - continue - id_ = self.id(index) + self._mi_for_col_color = 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, '') + + def get_column_color(key, fmt): 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) + if self._mi_for_col_color is None: + self._mi_for_col_color = self.db.get_metadata(id_, index_is_id=True) + mi = self._mi_for_col_color color = self.formatter.safe_format(fmt, mi, '', mi) if color in self.colors: color = QColor(color) @@ -746,7 +756,15 @@ class BooksModel(QAbstractTableModel): # {{{ self.color_cache[id_][key] = color return color except: - continue + pass + + for k, fmt in self.db.prefs['column_color_rules']: + if k == key: + col = get_column_color(key, fmt) + if col is not None: + self._mi_for_col_color = None + return col + if self.is_custom_column(key) and \ self.custom_columns[key]['datatype'] == 'enumeration': cc = self.custom_columns[self.column_map[col]]['display'] @@ -757,9 +775,19 @@ class BooksModel(QAbstractTableModel): # {{{ try: color = QColor(colors[values.index(txt)]) if color.isValid(): + self._mi_for_col_color = None return QVariant(color) except: pass + + if self.color_row_fmt_cache: + key = color_row_key + col = get_column_color(key, self.color_row_fmt_cache) + if col is not None: + self._mi_for_col_color = None + return col + + self._mi_for_col_color = 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..6a8be66e08 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -19,10 +19,12 @@ 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 +all_columns_string = _('All Columns') + class ConditionEditor(QWidget): # {{{ ACTION_MAP = { @@ -312,12 +314,10 @@ class RuleEditor(QDialog): # {{{ b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) - for key in sorted( - displayable_columns(fm), - key=sort_key): - name = fm[key]['name'] + for key in sorted(displayable_columns(fm), key=sort_key): + name = all_columns_string if key == color_row_key else fm[key]['name'] if name: - self.column_box.addItem(key, key) + self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) self.color_box.addItems(QColor.colorNames()) @@ -427,7 +427,8 @@ class RulesModel(QAbstractListModel): # {{{ col, rule = self.rules[row] except: return None - + if col == color_row_key: + col = all_columns_string 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..9366b3e5d7 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'):