Put column icons into separate rules and a separate preference.

This commit is contained in:
Charles Haley 2013-01-27 22:36:41 +01:00
parent 316a9539d8
commit e758b9fe42
4 changed files with 138 additions and 119 deletions

View File

@ -781,10 +781,12 @@ class BooksModel(QAbstractTableModel): # {{{
if col >= len(self.column_to_dc_map): if col >= len(self.column_to_dc_map):
return NONE return NONE
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
rules = self.db.prefs['column_icon_rules']
if rules:
key = self.column_map[col] key = self.column_map[col]
id_ = self.id(index) id_ = self.id(index)
self.column_icon.mi = None self.column_icon.mi = None
for kind, k, fmt in self.db.prefs['column_color_rules']: for kind, k, fmt in rules:
if k == key and kind == 'icon_only': if k == key and kind == 'icon_only':
ccicon = self.column_icon(id_, key, fmt, 'icon_only', self.db, ccicon = self.column_icon(id_, key, fmt, 'icon_only', self.db,
self.formatter, self.icon_cache) self.formatter, self.icon_cache)
@ -803,12 +805,11 @@ class BooksModel(QAbstractTableModel): # {{{
self.column_color.mi = None self.column_color.mi = None
if self.color_row_fmt_cache is None: if self.color_row_fmt_cache is None:
self.color_row_fmt_cache = tuple(fmt for kind, key, fmt in self.color_row_fmt_cache = tuple(fmt for key, fmt in
self.db.prefs['column_color_rules'] if kind == 'color' and self.db.prefs['column_color_rules'] if key == color_row_key)
key == color_row_key)
for kind, k, fmt in self.db.prefs['column_color_rules']: for k, fmt in self.db.prefs['column_color_rules']:
if k == key and kind == 'color': if k == key:
ccol = self.column_color(id_, key, fmt, self.db, ccol = self.column_color(id_, key, fmt, self.db,
self.formatter, self.color_cache, self.colors) self.formatter, self.color_cache, self.colors)
if ccol is not None: if ccol is not None:
@ -843,11 +844,13 @@ class BooksModel(QAbstractTableModel): # {{{
if ccicon != NONE: if ccicon != NONE:
return ccicon return ccicon
rules = self.db.prefs['column_icon_rules']
if rules:
key = self.column_map[col] key = self.column_map[col]
id_ = self.id(index) id_ = self.id(index)
self.column_icon.mi = None self.column_icon.mi = None
need_icon_with_text = False need_icon_with_text = False
for kind, k, fmt in self.db.prefs['column_color_rules']: for kind, k, fmt in rules:
if k == key and kind in ('icon', 'icon_only'): if k == key and kind in ('icon', 'icon_only'):
if kind == 'icon': if kind == 'icon':
need_icon_with_text = True need_icon_with_text = True

View File

@ -13,7 +13,7 @@ from PyQt4.Qt import (QWidget, QDialog, QLabel, QGridLayout, QComboBox, QSize,
QLineEdit, QIntValidator, QDoubleValidator, QFrame, QColor, Qt, QIcon, QLineEdit, QIntValidator, QDoubleValidator, QFrame, QColor, Qt, QIcon,
QScrollArea, QPushButton, QVBoxLayout, QDialogButtonBox, QToolButton, QScrollArea, QPushButton, QVBoxLayout, QDialogButtonBox, QToolButton,
QListView, QAbstractListModel, pyqtSignal, QSizePolicy, QSpacerItem, QListView, QAbstractListModel, pyqtSignal, QSizePolicy, QSpacerItem,
QApplication, QHBoxLayout) QApplication)
from calibre import prepare_string_for_xml, sanitize_file_name_unicode from calibre import prepare_string_for_xml, sanitize_file_name_unicode
from calibre.constants import config_dir from calibre.constants import config_dir
@ -28,8 +28,7 @@ from calibre.utils.icu import lower
all_columns_string = _('All Columns') all_columns_string = _('All Columns')
rule_kinds = [(_('color'), 'color'), icon_rule_kinds = [(_('icon with text'), 'icon'),
(_('icon with text'), 'icon'),
(_('icon with no text'), 'icon_only') ] (_('icon with no text'), 'icon_only') ]
class ConditionEditor(QWidget): # {{{ class ConditionEditor(QWidget): # {{{
@ -214,8 +213,6 @@ class ConditionEditor(QWidget): # {{{
col = self.current_col col = self.current_col
if not col: if not col:
return return
m = self.fm[col]
dt = m['datatype']
action = self.current_action action = self.current_action
if not action: if not action:
return return
@ -252,7 +249,7 @@ class ConditionEditor(QWidget): # {{{
class RuleEditor(QDialog): # {{{ class RuleEditor(QDialog): # {{{
def __init__(self, fm, parent=None): def __init__(self, fm, pref_name, parent=None):
QDialog.__init__(self, parent) QDialog.__init__(self, parent)
self.fm = fm self.fm = fm
@ -273,8 +270,13 @@ class RuleEditor(QDialog): # {{{
self.l2 = l2 = QLabel(_('Set the')) self.l2 = l2 = QLabel(_('Set the'))
l.addWidget(l2, 2, 0) l.addWidget(l2, 2, 0)
if pref_name == 'column_color_rules':
self.rule_kind = 'color'
l.addWidget(QLabel(_('color')))
else:
self.rule_kind = 'icon'
self.kind_box = QComboBox(self) self.kind_box = QComboBox(self)
for tt, t in rule_kinds: for tt, t in icon_rule_kinds:
self.kind_box.addItem(tt, t) self.kind_box.addItem(tt, t)
l.addWidget(self.kind_box, 2, 1) l.addWidget(self.kind_box, 2, 1)
@ -287,12 +289,13 @@ class RuleEditor(QDialog): # {{{
self.l4 = l4 = QLabel(_('to')) self.l4 = l4 = QLabel(_('to'))
l.addWidget(l4, 2, 4) l.addWidget(l4, 2, 4)
if self.rule_kind == 'color':
self.color_box = QComboBox(self) self.color_box = QComboBox(self)
self.color_label = QLabel('Sample text Sample text') self.color_label = QLabel('Sample text Sample text')
self.color_label.setTextFormat(Qt.RichText) self.color_label.setTextFormat(Qt.RichText)
l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_box, 2, 5)
l.addWidget(self.color_label, 2, 6) l.addWidget(self.color_label, 2, 6)
else:
self.filename_box = QLabel() self.filename_box = QLabel()
l.addWidget(self.filename_box, 2, 5) l.addWidget(self.filename_box, 2, 5)
self.filename_button = QPushButton(_('Choose icon')) self.filename_button = QPushButton(_('Choose icon'))
@ -331,24 +334,28 @@ class RuleEditor(QDialog): # {{{
self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions_widget.layout().setAlignment(Qt.AlignTop)
self.conditions = [] self.conditions = []
if self.rule_kind == 'color':
for b in (self.column_box, self.color_box): for b in (self.column_box, self.color_box):
b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon)
b.setMinimumContentsLength(15) b.setMinimumContentsLength(15)
for key in sorted(displayable_columns(fm), for key in sorted(displayable_columns(fm),
key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0): key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0):
if key == color_row_key and self.rule_kind != 'color':
continue
name = all_columns_string if key == color_row_key else fm[key]['name'] name = all_columns_string if key == color_row_key else fm[key]['name']
if name: if name:
self.column_box.addItem(name, key) self.column_box.addItem(name, key)
self.column_box.setCurrentIndex(0) self.column_box.setCurrentIndex(0)
if self.rule_kind == 'color':
self.color_box.addItems(QColor.colorNames()) self.color_box.addItems(QColor.colorNames())
self.color_box.setCurrentIndex(0) self.color_box.setCurrentIndex(0)
self.update_color_label() self.update_color_label()
self.color_box.currentIndexChanged.connect(self.update_color_label) self.color_box.currentIndexChanged.connect(self.update_color_label)
self.kind_box.currentIndexChanged[int].connect(self.kind_index_changed) else:
self.filename_button.clicked.connect(self.filename_button_clicked) self.filename_button.clicked.connect(self.filename_button_clicked)
self.resize(self.sizeHint()) self.resize(self.sizeHint())
self.icon_path = None self.icon_path = None
@ -363,18 +370,6 @@ class RuleEditor(QDialog): # {{{
<span style="color: {c}; background-color: {bg2}">&nbsp;{st}&nbsp;</span> <span style="color: {c}; background-color: {bg2}">&nbsp;{st}&nbsp;</span>
'''.format(c=c, bg1=bg1, bg2=bg2, st=_('Sample Text'))) '''.format(c=c, bg1=bg1, bg2=bg2, st=_('Sample Text')))
def kind_index_changed(self, dex):
if dex != 0:
self.color_label.setVisible(False)
self.color_box.setVisible(False)
self.filename_box.setVisible(True)
self.filename_button.setVisible(True)
else:
self.color_label.setVisible(True)
self.color_box.setVisible(True)
self.filename_box.setVisible(False)
self.filename_button.setVisible(False)
def filename_button_clicked(self): def filename_button_clicked(self):
try: try:
path = choose_files(self, 'choose_category_icon', path = choose_files(self, 'choose_category_icon',
@ -402,17 +397,12 @@ class RuleEditor(QDialog): # {{{
def apply_rule(self, kind, col, rule): def apply_rule(self, kind, col, rule):
if kind == 'color': if kind == 'color':
self.kind_box.setCurrentIndex(0)
self.filename_box.setVisible(False)
self.filename_button.setVisible(False)
if rule.color: if rule.color:
idx = self.color_box.findText(rule.color) idx = self.color_box.findText(rule.color)
if idx >= 0: if idx >= 0:
self.color_box.setCurrentIndex(idx) self.color_box.setCurrentIndex(idx)
else: else:
self.kind_box.setCurrentIndex(1 if kind == 'icon' else 2) self.kind_box.setCurrentIndex(0 if kind == 'icon' else 1)
self.color_box.setVisible(False)
self.color_label.setVisible(False)
self.filename_box.setText(rule.color) self.filename_box.setText(rule.color)
for i in range(self.column_box.count()): for i in range(self.column_box.count()):
@ -421,9 +411,11 @@ class RuleEditor(QDialog): # {{{
self.column_box.setCurrentIndex(i) self.column_box.setCurrentIndex(i)
break break
if rule.color: if rule.color:
if kind == 'color':
idx = self.color_box.findText(rule.color) idx = self.color_box.findText(rule.color)
if idx >= 0: if idx >= 0:
self.color_box.setCurrentIndex(idx) self.color_box.setCurrentIndex(idx)
else:
self.filename_box.setText(rule.color) self.filename_box.setText(rule.color)
for c in rule.conditions: for c in rule.conditions:
@ -438,7 +430,7 @@ class RuleEditor(QDialog): # {{{
def accept(self): def accept(self):
if self.kind_box.currentIndex() != 0: if self.rule_kind != 'color':
path = self.icon_path path = self.icon_path
if path: if path:
try: try:
@ -479,8 +471,7 @@ class RuleEditor(QDialog): # {{{
@property @property
def rule(self): def rule(self):
r = Rule(self.fm) r = Rule(self.fm)
kind = unicode(self.kind_box.itemData(self.kind_box.currentIndex()).toString()) if self.rule_kind != 'color':
if kind != 'color':
r.color = unicode(self.filename_box.text()) r.color = unicode(self.filename_box.text())
else: else:
r.color = unicode(self.color_box.currentText()) r.color = unicode(self.color_box.currentText())
@ -490,20 +481,39 @@ class RuleEditor(QDialog): # {{{
condition = c.condition condition = c.condition
if condition is not None: if condition is not None:
r.add_condition(*condition) r.add_condition(*condition)
if self.rule_kind == 'icon':
kind = unicode(self.kind_box.itemData(
self.kind_box.currentIndex()).toString())
else:
kind = 'color'
return kind, col, r return kind, col, r
# }}} # }}}
class RulesModel(QAbstractListModel): # {{{ class RulesModel(QAbstractListModel): # {{{
def __init__(self, prefs, fm, parent=None): def __init__(self, prefs, fm, pref_name, parent=None):
QAbstractListModel.__init__(self, parent) QAbstractListModel.__init__(self, parent)
self.fm = fm self.fm = fm
rules = list(prefs['column_color_rules']) self.pref_name = pref_name
if pref_name == 'column_color_rules':
self.rule_kind = 'color'
rules = list(prefs[pref_name])
self.rules = []
for col, template in rules:
if col not in self.fm and col != color_row_key: continue
try:
rule = rule_from_template(self.fm, template)
except:
rule = template
self.rules.append(('color', col, rule))
else:
self.rule_kind = 'icon'
rules = list(prefs[pref_name])
self.rules = [] self.rules = []
for kind, col, template in rules: for kind, col, template in rules:
if col not in self.fm: continue if col not in self.fm and col != color_row_key: continue
try: try:
rule = rule_from_template(self.fm, template) rule = rule_from_template(self.fm, template)
except: except:
@ -547,8 +557,11 @@ class RulesModel(QAbstractListModel): # {{{
if isinstance(r, Rule): if isinstance(r, Rule):
r = r.template r = r.template
if r is not None: if r is not None:
if kind == 'color':
rules.append((col, r))
else:
rules.append((kind, col, r)) rules.append((kind, col, r))
prefs['column_color_rules'] = rules prefs[self.pref_name] = rules
def move(self, idx, delta): def move(self, idx, delta):
row = idx.row() + delta row = idx.row() + delta
@ -574,7 +587,10 @@ class RulesModel(QAbstractListModel): # {{{
conditions = [self.condition_to_html(c) for c in rule.conditions] conditions = [self.condition_to_html(c) for c in rule.conditions]
trans_kind = 'not found' trans_kind = 'not found'
for tt, t in rule_kinds: if kind == 'color':
trans_kind = _('color')
else:
for tt, t in icon_rule_kinds:
if kind == t: if kind == t:
trans_kind = tt trans_kind = tt
break break
@ -656,8 +672,9 @@ class EditRules(QWidget): # {{{
b.clicked.connect(self.add_advanced) b.clicked.connect(self.add_advanced)
l.addWidget(b, 3, 0, 1, 2) l.addWidget(b, 3, 0, 1, 2)
def initialize(self, fm, prefs, mi): def initialize(self, fm, prefs, mi, pref_name):
self.model = RulesModel(prefs, fm) self.pref_name = pref_name
self.model = RulesModel(prefs, fm, self.pref_name)
self.rules_view.setModel(self.model) self.rules_view.setModel(self.model)
self.fm = fm self.fm = fm
self.mi = mi self.mi = mi
@ -671,7 +688,7 @@ class EditRules(QWidget): # {{{
self.changed.emit() self.changed.emit()
def add_rule(self): def add_rule(self):
d = RuleEditor(self.model.fm) d = RuleEditor(self.model.fm, self.pref_name)
d.add_blank_condition() d.add_blank_condition()
self._add_rule(d) self._add_rule(d)
@ -685,7 +702,7 @@ class EditRules(QWidget): # {{{
except: except:
return return
if isinstance(rule, Rule): if isinstance(rule, Rule):
d = RuleEditor(self.model.fm) d = RuleEditor(self.model.fm, self.pref_name)
d.apply_rule(kind, col, rule) d.apply_rule(kind, col, rule)
else: else:
d = TemplateDialog(self, rule, mi=self.mi, fm=self.fm, color_field=col) d = TemplateDialog(self, rule, mi=self.mi, fm=self.fm, color_field=col)
@ -748,7 +765,7 @@ if __name__ == '__main__':
db = db() db = db()
if True: if True:
d = RuleEditor(db.field_metadata) d = RuleEditor(db.field_metadata, 'column_color_rules')
d.add_blank_condition() d.add_blank_condition()
d.exec_() d.exec_()

View File

@ -181,6 +181,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.edit_rules.changed.connect(self.changed_signal) self.edit_rules.changed.connect(self.changed_signal)
self.tabWidget.addTab(self.edit_rules, self.tabWidget.addTab(self.edit_rules,
QIcon(I('format-fill-color.png')), _('Column coloring')) QIcon(I('format-fill-color.png')), _('Column coloring'))
self.icon_rules = EditRules(self.tabWidget)
self.icon_rules.changed.connect(self.changed_signal)
self.tabWidget.addTab(self.icon_rules,
QIcon(I('format-fill-color.png')), _('Column icons'))
self.tabWidget.setCurrentIndex(0) self.tabWidget.setCurrentIndex(0)
keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence( keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
'Ctrl+Shift+F', QKeySequence.PortableText)] 'Ctrl+Shift+F', QKeySequence.PortableText)]
@ -203,7 +209,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
mi = db.get_metadata(idx, index_is_id=False) mi = db.get_metadata(idx, index_is_id=False)
except: except:
mi=None mi=None
self.edit_rules.initialize(db.field_metadata, db.prefs, mi) self.edit_rules.initialize(db.field_metadata, db.prefs, mi, 'column_color_rules')
self.icon_rules.initialize(db.field_metadata, db.prefs, mi, 'column_icon_rules')
def restore_defaults(self): def restore_defaults(self):
ConfigWidgetBase.restore_defaults(self) ConfigWidgetBase.restore_defaults(self)
@ -214,6 +221,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.update_font_display() self.update_font_display()
self.display_model.restore_defaults() self.display_model.restore_defaults()
self.edit_rules.clear() self.edit_rules.clear()
self.icon_rules.clear()
self.changed_signal.emit() self.changed_signal.emit()
def build_font_obj(self): def build_font_obj(self):
@ -273,6 +281,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
rr = True rr = True
self.display_model.commit() self.display_model.commit()
self.edit_rules.commit(self.gui.current_db.prefs) self.edit_rules.commit(self.gui.current_db.prefs)
self.icon_rules.commit(self.gui.current_db.prefs)
return rr return rr
def refresh_gui(self, gui): def refresh_gui(self, gui):

View File

@ -211,6 +211,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
defs['gui_restriction'] = defs['cs_restriction'] = '' defs['gui_restriction'] = defs['cs_restriction'] = ''
defs['categories_using_hierarchy'] = [] defs['categories_using_hierarchy'] = []
defs['column_color_rules'] = [] defs['column_color_rules'] = []
defs['column_icon_rules'] = []
defs['grouped_search_make_user_categories'] = [] defs['grouped_search_make_user_categories'] = []
defs['similar_authors_search_key'] = 'authors' defs['similar_authors_search_key'] = 'authors'
defs['similar_authors_match_kind'] = 'match_any' defs['similar_authors_match_kind'] = 'match_any'
@ -253,17 +254,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if old_rules: if old_rules:
self.prefs['column_color_rules'] += old_rules self.prefs['column_color_rules'] += old_rules
new_rules = []
must_save_new_rules = False
for tup in self.prefs['column_color_rules']:
if len(tup) == 2:
must_save_new_rules = True;
new_rules.append( ('color', tup[0], tup[1]) )
else:
new_rules.append(tup)
if must_save_new_rules:
self.prefs['column_color_rules'] = new_rules
# Migrate saved search and user categories to db preference scheme # Migrate saved search and user categories to db preference scheme
def migrate_preference(key, default): def migrate_preference(key, default):
oldval = prefs[key] oldval = prefs[key]