New preferences interface for column coloring. Note that editing of advanced rules is not yet implemented.

This commit is contained in:
Kovid Goyal 2011-06-01 21:47:03 -06:00
parent f6f8963653
commit 6b8a1442c1
6 changed files with 79 additions and 312 deletions

View File

@ -99,8 +99,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.ids_to_highlight_set = set() self.ids_to_highlight_set = set()
self.current_highlighted_idx = None self.current_highlighted_idx = None
self.highlight_only = False self.highlight_only = False
self.column_color_list = [] self.colors = frozenset([unicode(c) for c in QColor.colorNames()])
self.colors = [unicode(c) for c in QColor.colorNames()]
self.read_config() self.read_config()
def change_alignment(self, colname, alignment): def change_alignment(self, colname, alignment):
@ -156,7 +155,6 @@ class BooksModel(QAbstractTableModel): # {{{
self.headers[col] = self.custom_columns[col]['name'] self.headers[col] = self.custom_columns[col]['name']
self.build_data_convertors() self.build_data_convertors()
self.set_color_templates(reset=False)
self.reset() self.reset()
self.database_changed.emit(db) self.database_changed.emit(db)
self.stop_metadata_backup() self.stop_metadata_backup()
@ -545,16 +543,6 @@ class BooksModel(QAbstractTableModel): # {{{
img = self.default_image img = self.default_image
return img return img
def set_color_templates(self, reset=True):
self.column_color_list = []
for i in range(1,self.db.column_color_count+1):
name = self.db.prefs.get('column_color_name_'+str(i))
if name:
self.column_color_list.append((name,
self.db.prefs.get('column_color_template_'+str(i))))
if reset:
self.reset()
def build_data_convertors(self): def build_data_convertors(self):
def authors(r, idx=-1): def authors(r, idx=-1):
au = self.db.data[r][idx] au = self.db.data[r][idx]
@ -726,14 +714,16 @@ class BooksModel(QAbstractTableModel): # {{{
return QVariant(QColor('lightgreen')) return QVariant(QColor('lightgreen'))
elif role == Qt.ForegroundRole: elif role == Qt.ForegroundRole:
key = self.column_map[col] key = self.column_map[col]
for k,fmt in self.column_color_list: mi = None
for k, fmt in self.db.prefs['column_color_rules']:
if k != key: if k != key:
continue continue
id_ = self.id(index) id_ = self.id(index)
if id_ in self.color_cache: if id_ in self.color_cache:
if key in self.color_cache[id_]: if key in self.color_cache[id_]:
return self.color_cache[id_][key] return self.color_cache[id_][key]
mi = self.db.get_metadata(self.id(index), index_is_id=True) if mi is None:
mi = self.db.get_metadata(id_, index_is_id=True)
try: try:
color = composite_formatter.safe_format(fmt, mi, '', mi) color = composite_formatter.safe_format(fmt, mi, '', mi)
if color in self.colors: if color in self.colors:
@ -743,7 +733,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.color_cache[id_][key] = color self.color_cache[id_][key] = color
return color return color
except: except:
return NONE continue
if self.is_custom_column(key) and \ if self.is_custom_column(key) and \
self.custom_columns[key]['datatype'] == 'enumeration': self.custom_columns[key]['datatype'] == 'enumeration':
cc = self.custom_columns[self.column_map[col]]['display'] cc = self.custom_columns[self.column_map[col]]['display']

View File

@ -10,10 +10,11 @@ __docformat__ = 'restructuredtext en'
from PyQt4.Qt import (QWidget, QDialog, QLabel, QGridLayout, QComboBox, QSize, 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) QListView, QAbstractListModel, pyqtSignal)
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.gui2 import error_dialog from calibre.gui2 import error_dialog
from calibre.gui2.dialogs.template_dialog import TemplateDialog
from calibre.gui2.metadata.single_download import RichTextDelegate from calibre.gui2.metadata.single_download import RichTextDelegate
from calibre.library.coloring import (Rule, conditionable_columns, from calibre.library.coloring import (Rule, conditionable_columns,
displayable_columns, rule_from_template) displayable_columns, rule_from_template)
@ -402,6 +403,10 @@ class RulesModel(QAbstractListModel):
self.dataChanged.emit(idx, idx) self.dataChanged.emit(idx, idx)
return idx return idx
def clear(self):
self.rules = []
self.reset()
def rule_to_html(self, col, rule): def rule_to_html(self, col, rule):
if isinstance(rule, basestring): if isinstance(rule, basestring):
return _(''' return _('''
@ -422,6 +427,8 @@ class RulesModel(QAbstractListModel):
class EditRules(QWidget): class EditRules(QWidget):
changed = pyqtSignal()
def __init__(self, parent=None): def __init__(self, parent=None):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
@ -479,13 +486,20 @@ class EditRules(QWidget):
self.rules_view.setModel(self.model) self.rules_view.setModel(self.model)
def add_rule(self): def add_rule(self):
d = RuleEditor(db.field_metadata) d = RuleEditor(self.model.fm)
d.add_blank_condition() d.add_blank_condition()
if d.exec_() == d.Accepted: if d.exec_() == d.Accepted:
col, r = d.rule col, r = d.rule
if r is not None and col: if r is not None and col:
idx = self.model.add_rule(col, r) idx = self.model.add_rule(col, r)
self.rules_view.scrollTo(idx) self.rules_view.scrollTo(idx)
self.changed.emit()
def add_advanced(self):
td = TemplateDialog(self, '', None)
if td.exec_() == td.Accepted:
self.changed.emit()
pass # TODO
def edit_rule(self, index): def edit_rule(self, index):
try: try:
@ -493,19 +507,20 @@ class EditRules(QWidget):
except: except:
return return
if isinstance(rule, Rule): if isinstance(rule, Rule):
d = RuleEditor(db.field_metadata) d = RuleEditor(self.model.fm)
d.apply_rule(col, rule) d.apply_rule(col, rule)
if d.exec_() == d.Accepted: if d.exec_() == d.Accepted:
col, r = d.rule col, r = d.rule
if r is not None and col: if r is not None and col:
self.model.replace_rule(index, col, r) self.model.replace_rule(index, col, r)
self.rules_view.scrollTo(index) self.rules_view.scrollTo(index)
self.changed.emit()
else: else:
td = TemplateDialog(self, rule, None)
if td.exec_() == td.Accepted:
self.changed.emit()
pass # TODO pass # TODO
def add_advanced(self):
pass
def get_selected_row(self, txt): def get_selected_row(self, txt):
sm = self.rules_view.selectionModel() sm = self.rules_view.selectionModel()
rows = list(sm.selectedRows()) rows = list(sm.selectedRows())
@ -519,6 +534,7 @@ class EditRules(QWidget):
row = self.get_selected_row(_('removal')) row = self.get_selected_row(_('removal'))
if row is not None: if row is not None:
self.model.remove_rule(row) self.model.remove_rule(row)
self.changed.emit()
def move_up(self): def move_up(self):
idx = self.rules_view.currentIndex() idx = self.rules_view.currentIndex()
@ -528,6 +544,7 @@ class EditRules(QWidget):
sm = self.rules_view.selectionModel() sm = self.rules_view.selectionModel()
sm.select(idx, sm.ClearAndSelect) sm.select(idx, sm.ClearAndSelect)
self.rules_view.setCurrentIndex(idx) self.rules_view.setCurrentIndex(idx)
self.changed.emit()
def move_down(self): def move_down(self):
idx = self.rules_view.currentIndex() idx = self.rules_view.currentIndex()
@ -537,6 +554,11 @@ class EditRules(QWidget):
sm = self.rules_view.selectionModel() sm = self.rules_view.selectionModel()
sm.select(idx, sm.ClearAndSelect) sm.select(idx, sm.ClearAndSelect)
self.rules_view.setCurrentIndex(idx) self.rules_view.setCurrentIndex(idx)
self.changed.emit()
def clear(self):
self.model.clear()
self.changed.emit()
def commit(self, prefs): def commit(self, prefs):
self.model.commit(prefs) self.model.commit(prefs)

View File

@ -5,21 +5,19 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from functools import partial
from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog, from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog,
QAbstractListModel, Qt, QColor, QIcon, QToolButton, QComboBox) QAbstractListModel, Qt, QIcon)
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList
from calibre.gui2.preferences.look_feel_ui import Ui_Form from calibre.gui2.preferences.look_feel_ui import Ui_Form
from calibre.gui2 import config, gprefs, qt_app from calibre.gui2 import config, gprefs, qt_app
from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor
from calibre.utils.localization import (available_translations, from calibre.utils.localization import (available_translations,
get_language, get_lang) get_language, get_lang)
from calibre.utils.config import prefs from calibre.utils.config import prefs
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.gui2 import NONE from calibre.gui2 import NONE
from calibre.gui2.book_details import get_field_list from calibre.gui2.book_details import get_field_list
from calibre.gui2.preferences.coloring import EditRules
class DisplayedFields(QAbstractListModel): # {{{ class DisplayedFields(QAbstractListModel): # {{{
@ -162,117 +160,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.df_up_button.clicked.connect(self.move_df_up) self.df_up_button.clicked.connect(self.move_df_up)
self.df_down_button.clicked.connect(self.move_df_down) self.df_down_button.clicked.connect(self.move_df_down)
self.color_help_text.setText('<p>' + self.edit_rules = EditRules(self.tabWidget)
_('Here you can specify coloring rules for columns shown in the ' self.edit_rules.changed.connect(self.changed_signal)
'library view. Choose the column you wish to color, then ' self.tabWidget.addTab(self.edit_rules,
'supply a template that specifies the color to use based on ' QIcon(I('format-fill-color.png')), _('Column coloring'))
'the values in the column. There is a ' self.tabWidget.setCurrentIndex(0)
'<a href="http://manual.calibre-ebook.com/template_lang.html">'
'tutorial</a> on using templates.') +
'</p><p>' +
_('If you want to color a field based on contents of columns, '
'then click the button next to an empty line to open the wizard. '
'It will build a template for you. You can later edit that '
'template with the same wizard. This is by far the easiest '
'way to specify a template.') +
'</p><p>' +
_('If you manually construct a template, then the template must '
'evaluate to a valid color name shown in the color names box.'
'You can use any legal template expression. '
'For example, you can set the title to always display in '
'green using the template "green" (without the quotes). '
'To show the title in the color named in the custom column '
'#column, use "{#column}". To show the title in blue if the '
'custom column #column contains the value "foo", in red if the '
'column contains the value "bar", otherwise in black, use '
'<pre>{#column:switch(foo,blue,bar,red,black)}</pre>'
'To show the title in blue if the book has the exact tag '
'"Science Fiction", red if the book has the exact tag '
'"Mystery", or black if the book has neither tag, use'
"<pre>program: \n"
" t = field('tags'); \n"
" first_non_empty(\n"
" in_list(t, ',', '^Science Fiction$', 'blue', ''), \n"
" in_list(t, ',', '^Mystery$', 'red', 'black'))</pre>"
'To show the title in green if it has one format, blue if it '
'two formats, and red if more, use'
"<pre>program:cmp(count(field('formats'),','), 2, 'green', 'blue', 'red')</pre>") +
'</p><p>' +
_('You can access a multi-line template editor from the '
'context menu (right-click).') + '</p><p>' +
_('<b>Note:</b> if you want to color a "custom column with a fixed set '
'of values", it is often easier to specify the '
'colors in the column definition dialog. There you can '
'provide a color for each value without using a template.')+ '</p>')
self.color_help_scrollArea.setVisible(False)
self.color_help_button.clicked.connect(self.change_help_text)
self.colors_scrollArea.setVisible(False)
self.colors_label.setVisible(False)
self.colors_button.clicked.connect(self.change_colors_text)
choices = db.field_metadata.displayable_field_keys()
choices.sort(key=sort_key)
choices.insert(0, '')
self.column_color_count = db.column_color_count+1
mi=None
try:
idx = gui.library_view.currentIndex().row()
mi = db.get_metadata(idx, index_is_id=False)
except:
pass
l = self.column_color_layout
for i in range(1, self.column_color_count):
ccn = QComboBox(parent=self)
setattr(self, 'opt_column_color_name_'+str(i), ccn)
l.addWidget(ccn, i, 0, 1, 1)
wtb = QToolButton(parent=self)
setattr(self, 'opt_column_color_wizard_'+str(i), wtb)
wtb.setIcon(QIcon(I('wizard.png')))
l.addWidget(wtb, i, 1, 1, 1)
ttb = QToolButton(parent=self)
setattr(self, 'opt_column_color_tpledit_'+str(i), ttb)
ttb.setIcon(QIcon(I('edit_input.png')))
l.addWidget(ttb, i, 2, 1, 1)
tpl = TemplateLineEditor(parent=self)
setattr(self, 'opt_column_color_template_'+str(i), tpl)
tpl.textChanged.connect(partial(self.tpl_edit_text_changed, ctrl=i))
tpl.set_db(db)
tpl.set_mi(mi)
l.addWidget(tpl, i, 3, 1, 1)
wtb.clicked.connect(tpl.tag_wizard)
ttb.clicked.connect(tpl.open_editor)
r('column_color_name_'+str(i), db.prefs, choices=choices)
r('column_color_template_'+str(i), db.prefs)
txt = db.prefs.get('column_color_template_'+str(i), None)
wtb.setEnabled(tpl.enable_wizard_button(txt))
ttb.setEnabled(not tpl.enable_wizard_button(txt) or not txt)
all_colors = [unicode(s) for s in list(QColor.colorNames())]
self.colors_box.setText(', '.join(all_colors))
def change_help_text(self):
self.color_help_scrollArea.setVisible(not self.color_help_scrollArea.isVisible())
def change_colors_text(self):
self.colors_scrollArea.setVisible(not self.colors_scrollArea.isVisible())
self.colors_label.setVisible(not self.colors_label.isVisible())
def tpl_edit_text_changed(self, ign, ctrl=None):
tpl = getattr(self, 'opt_column_color_template_'+str(ctrl))
txt = unicode(tpl.text())
wtb = getattr(self, 'opt_column_color_wizard_'+str(ctrl))
ttb = getattr(self, 'opt_column_color_tpledit_'+str(ctrl))
wtb.setEnabled(tpl.enable_wizard_button(txt))
ttb.setEnabled(not tpl.enable_wizard_button(txt) or not txt)
tpl.setFocus()
def initialize(self): def initialize(self):
ConfigWidgetBase.initialize(self) ConfigWidgetBase.initialize(self)
@ -283,6 +175,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.current_font = self.initial_font = font self.current_font = self.initial_font = font
self.update_font_display() self.update_font_display()
self.display_model.initialize() self.display_model.initialize()
db = self.gui.current_db
self.edit_rules.initialize(db.field_metadata, db.prefs)
def restore_defaults(self): def restore_defaults(self):
ConfigWidgetBase.restore_defaults(self) ConfigWidgetBase.restore_defaults(self)
@ -292,6 +186,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.changed_signal.emit() self.changed_signal.emit()
self.update_font_display() self.update_font_display()
self.display_model.restore_defaults() self.display_model.restore_defaults()
self.edit_rules.clear()
self.changed_signal.emit() self.changed_signal.emit()
def build_font_obj(self): def build_font_obj(self):
@ -341,12 +236,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.changed_signal.emit() self.changed_signal.emit()
def commit(self, *args): def commit(self, *args):
for i in range(1, self.column_color_count):
col = getattr(self, 'opt_column_color_name_'+str(i))
tpl = getattr(self, 'opt_column_color_template_'+str(i))
if not col.currentIndex() or not unicode(tpl.text()).strip():
col.setCurrentIndex(0)
tpl.setText('')
rr = ConfigWidgetBase.commit(self, *args) rr = ConfigWidgetBase.commit(self, *args)
if self.current_font != self.initial_font: if self.current_font != self.initial_font:
gprefs['font'] = (self.current_font[:4] if self.current_font else gprefs['font'] = (self.current_font[:4] if self.current_font else
@ -356,10 +245,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
QApplication.setFont(self.font_display.font()) QApplication.setFont(self.font_display.font())
rr = True rr = True
self.display_model.commit() self.display_model.commit()
self.edit_rules.commit(self.gui.current_db.prefs)
return rr return rr
def refresh_gui(self, gui): def refresh_gui(self, gui):
gui.library_view.model().set_color_templates() gui.library_view.model().reset()
self.update_font_display() self.update_font_display()
gui.tags_view.reread_collapse_parameters() gui.tags_view.reread_collapse_parameters()
gui.library_view.refresh_book_details() gui.library_view.refresh_book_details()

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>717</width> <width>820</width>
<height>519</height> <height>519</height>
</rect> </rect>
</property> </property>
@ -407,161 +407,6 @@ then the tags will be displayed each on their own line.</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_5">
<attribute name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/format-fill-color.png</normaloff>:/images/format-fill-color.png</iconset>
</attribute>
<attribute name="title">
<string>Column Coloring</string>
</attribute>
<layout class="QGridLayout" name="column_color_layout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Column to color</string>
</property>
</widget>
</item>
<item row="0" column="3">
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Color selection template</string>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>10</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>The template wizard is easiest to use</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="color_help_button">
<property name="text">
<string>Show/hide help text</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="colors_button">
<property name="text">
<string>Show/hide colors</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="20" column="0">
<widget class="QLabel" name="colors_label">
<property name="text">
<string>Color names</string>
</property>
</widget>
</item>
<item row="21" column="0" colspan="8">
<widget class="QScrollArea" name="colors_scrollArea">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>300</height>
</size>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>687</width>
<height>61</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="colors_box">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="30" column="0" colspan="8">
<widget class="QScrollArea" name="color_help_scrollArea">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeft|Qt::AlignTop</set>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>687</width>
<height>194</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="color_help_text">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="40" column="0">
<spacer>
<property name="sizePolicy">
<sizepolicy vsizetype="Expanding" hsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>10</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -572,11 +417,6 @@ then the tags will be displayed each on their own line.</string>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header>calibre/gui2/complete.h</header> <header>calibre/gui2/complete.h</header>
</customwidget> </customwidget>
<customwidget>
<class>TemplateLineEditor</class>
<extends>QLineEdit</extends>
<header>calibre/gui2/dialogs/template_line_editor.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../../../../resources/images.qrc"/> <include location="../../../../resources/images.qrc"/>

View File

@ -61,7 +61,7 @@ class Rule(object): # {{{
{sig} {sig}
test(and( test(and(
{conditions} {conditions}
), {color}, ''); ), '{color}', '');
''').format(sig=self.signature, conditions=conditions, ''').format(sig=self.signature, conditions=conditions,
color=self.color) color=self.color)
@ -169,10 +169,21 @@ def conditionable_columns(fm):
'comments', 'text', 'enumeration', 'datetime'): 'comments', 'text', 'enumeration', 'datetime'):
yield key yield key
def displayable_columns(fm): def displayable_columns(fm):
for key in fm.displayable_field_keys(): for key in fm.displayable_field_keys():
if key not in ('sort', 'author_sort', 'comments', 'formats', if key not in ('sort', 'author_sort', 'comments', 'formats',
'identifiers', 'path'): 'identifiers', 'path'):
yield key yield key
def migrate_old_rule(fm, template):
if template.startswith('program:\n#tag wizard'):
rules = []
for line in template.splitlines():
if line.startswith('#') and ':|:' in line:
value, color = line[1:].split(':|:')
r = Rule(fm, color=color)
r.add_condition('tags', 'has', value)
rules.append(r.template)
return rules
return template

View File

@ -211,10 +211,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
defs = self.prefs.defaults defs = self.prefs.defaults
defs['gui_restriction'] = defs['cs_restriction'] = '' defs['gui_restriction'] = defs['cs_restriction'] = ''
defs['categories_using_hierarchy'] = [] defs['categories_using_hierarchy'] = []
self.column_color_count = 5 defs['column_color_rules'] = []
for i in range(1,self.column_color_count+1):
defs['column_color_name_'+str(i)] = ''
defs['column_color_template_'+str(i)] = ''
# Migrate the bool tristate tweak # Migrate the bool tristate tweak
defs['bools_are_tristate'] = \ defs['bools_are_tristate'] = \
@ -222,6 +219,23 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if self.prefs.get('bools_are_tristate') is None: if self.prefs.get('bools_are_tristate') is None:
self.prefs.set('bools_are_tristate', defs['bools_are_tristate']) self.prefs.set('bools_are_tristate', defs['bools_are_tristate'])
# Migrate column coloring rules
if self.prefs.get('column_color_name_1', None) is not None:
from calibre.library.coloring import migrate_old_rule
old_rules = []
for i in range(1, 5):
col = self.prefs.get('column_color_name_'+str(i), None)
templ = self.prefs.get('column_color_template_'+str(i), None)
if col and templ:
try:
del self.prefs['column_color_name_'+str(i)]
templ = migrate_old_rule(self.field_metadata, templ)
old_rules.append((col, templ))
except:
pass
if old_rules:
self.prefs['column_color_rules'] += old_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]