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,16 +781,18 @@ class BooksModel(QAbstractTableModel): # {{{
if col >= len(self.column_to_dc_map):
return NONE
if role == Qt.DisplayRole:
key = self.column_map[col]
id_ = self.id(index)
self.column_icon.mi = None
for kind, k, fmt in self.db.prefs['column_color_rules']:
if k == key and kind == 'icon_only':
ccicon = self.column_icon(id_, key, fmt, 'icon_only', self.db,
self.formatter, self.icon_cache)
if ccicon is not None:
return NONE
self.icon_cache[id_][key+'icon_only'] = None
rules = self.db.prefs['column_icon_rules']
if rules:
key = self.column_map[col]
id_ = self.id(index)
self.column_icon.mi = None
for kind, k, fmt in rules:
if k == key and kind == 'icon_only':
ccicon = self.column_icon(id_, key, fmt, 'icon_only', self.db,
self.formatter, self.icon_cache)
if ccicon is not None:
return NONE
self.icon_cache[id_][key+'icon_only'] = None
return self.column_to_dc_map[col](index.row())
elif role in (Qt.EditRole, Qt.ToolTipRole):
return self.column_to_dc_map[col](index.row())
@ -803,12 +805,11 @@ class BooksModel(QAbstractTableModel): # {{{
self.column_color.mi = None
if self.color_row_fmt_cache is None:
self.color_row_fmt_cache = tuple(fmt for kind, key, fmt in
self.db.prefs['column_color_rules'] if kind == 'color' and
key == color_row_key)
self.color_row_fmt_cache = tuple(fmt for key, fmt in
self.db.prefs['column_color_rules'] if key == color_row_key)
for kind, k, fmt in self.db.prefs['column_color_rules']:
if k == key and kind == 'color':
for k, fmt in self.db.prefs['column_color_rules']:
if k == key:
ccol = self.column_color(id_, key, fmt, self.db,
self.formatter, self.color_cache, self.colors)
if ccol is not None:
@ -843,22 +844,24 @@ class BooksModel(QAbstractTableModel): # {{{
if ccicon != NONE:
return ccicon
key = self.column_map[col]
id_ = self.id(index)
self.column_icon.mi = None
need_icon_with_text = False
for kind, k, fmt in self.db.prefs['column_color_rules']:
if k == key and kind in ('icon', 'icon_only'):
if kind == 'icon':
need_icon_with_text = True
ccicon = self.column_icon(id_, key, fmt, 'icon', self.db,
self.formatter, self.icon_cache)
if ccicon is not None:
return ccicon
if need_icon_with_text:
self.icon_cache[id_][key+'icon'] = self.bool_blank_icon
return self.bool_blank_icon
self.icon_cache[id_][key+'icon'] = None
rules = self.db.prefs['column_icon_rules']
if rules:
key = self.column_map[col]
id_ = self.id(index)
self.column_icon.mi = None
need_icon_with_text = False
for kind, k, fmt in rules:
if k == key and kind in ('icon', 'icon_only'):
if kind == 'icon':
need_icon_with_text = True
ccicon = self.column_icon(id_, key, fmt, 'icon', self.db,
self.formatter, self.icon_cache)
if ccicon is not None:
return ccicon
if need_icon_with_text:
self.icon_cache[id_][key+'icon'] = self.bool_blank_icon
return self.bool_blank_icon
self.icon_cache[id_][key+'icon'] = None
elif role == Qt.TextAlignmentRole:
cname = self.column_map[index.column()]
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,

View File

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

View File

@ -181,6 +181,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.edit_rules.changed.connect(self.changed_signal)
self.tabWidget.addTab(self.edit_rules,
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)
keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
'Ctrl+Shift+F', QKeySequence.PortableText)]
@ -203,7 +209,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
mi = db.get_metadata(idx, index_is_id=False)
except:
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):
ConfigWidgetBase.restore_defaults(self)
@ -214,6 +221,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.update_font_display()
self.display_model.restore_defaults()
self.edit_rules.clear()
self.icon_rules.clear()
self.changed_signal.emit()
def build_font_obj(self):
@ -273,6 +281,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
rr = True
self.display_model.commit()
self.edit_rules.commit(self.gui.current_db.prefs)
self.icon_rules.commit(self.gui.current_db.prefs)
return rr
def refresh_gui(self, gui):

View File

@ -211,6 +211,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
defs['gui_restriction'] = defs['cs_restriction'] = ''
defs['categories_using_hierarchy'] = []
defs['column_color_rules'] = []
defs['column_icon_rules'] = []
defs['grouped_search_make_user_categories'] = []
defs['similar_authors_search_key'] = 'authors'
defs['similar_authors_match_kind'] = 'match_any'
@ -253,17 +254,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if 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
def migrate_preference(key, default):
oldval = prefs[key]