From d3f26a14dc33776476702420dae9f190b7dc08da Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Fri, 8 Apr 2011 15:44:22 +0100
Subject: [PATCH 1/3] Add metadata editor selector to custom columns
preferences dialog
---
src/calibre/gui2/metadata/single.py | 8 +++-
src/calibre/gui2/preferences/columns.py | 9 ++++
src/calibre/gui2/preferences/columns.ui | 61 +++++++++++++++++++++++++
src/calibre/library/database2.py | 2 +
4 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py
index 4f66e0d2ba..cba877b249 100644
--- a/src/calibre/gui2/metadata/single.py
+++ b/src/calibre/gui2/metadata/single.py
@@ -521,7 +521,7 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
# }}}
-class MetadataSingleDialogAlt(MetadataSingleDialogBase): # {{{
+class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
cc_two_column = False
one_line_comments_toolbar = True
@@ -654,10 +654,14 @@ class MetadataSingleDialogAlt(MetadataSingleDialogBase): # {{{
# }}}
+editors = {'default': MetadataSingleDialog, 'alt1': MetadataSingleDialogAlt1}
def edit_metadata(db, row_list, current_row, parent=None, view_slot=None,
set_current_callback=None):
- d = MetadataSingleDialog(db, parent)
+ cls = db.prefs.get('edit_metadata_single_layout', '')
+ if cls not in editors:
+ cls = 'default'
+ d = editors[cls](db, parent)
d.start(row_list, current_row, view_slot=view_slot,
set_current_callback=set_current_callback)
return d.changed, d.rows_to_refresh
diff --git a/src/calibre/gui2/preferences/columns.py b/src/calibre/gui2/preferences/columns.py
index 03a50e6f3a..7c57054253 100644
--- a/src/calibre/gui2/preferences/columns.py
+++ b/src/calibre/gui2/preferences/columns.py
@@ -13,6 +13,7 @@ from calibre.gui2.preferences import ConfigWidgetBase, test_widget
from calibre.gui2.preferences.columns_ui import Ui_Form
from calibre.gui2.preferences.create_custom_column import CreateCustomColumn
from calibre.gui2 import error_dialog, question_dialog, ALL_COLUMNS
+from calibre.utils.config import test_eight_code
class ConfigWidget(ConfigWidgetBase, Ui_Form):
@@ -33,6 +34,14 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
signal = getattr(self.opt_columns, 'item'+signal)
signal.connect(self.columns_changed)
+ if test_eight_code:
+ r = self.register
+ choices = [(_('Default'), 'default'), (_('Compact Metadata'), 'alt1')]
+ r('edit_metadata_single_layout', db.prefs, choices=choices)
+ r('bools_are_tristate', db.prefs)
+ else:
+ self.items_in_v_eight.setVisible(False)
+
def initialize(self):
ConfigWidgetBase.initialize(self)
self.init_columns()
diff --git a/src/calibre/gui2/preferences/columns.ui b/src/calibre/gui2/preferences/columns.ui
index a9d82530ec..685a5ab847 100644
--- a/src/calibre/gui2/preferences/columns.ui
+++ b/src/calibre/gui2/preferences/columns.ui
@@ -197,6 +197,67 @@
+ -
+
+
-
+
+
+ Related Options
+
+
+
-
+
+
+ Edit metadata layout:
+
+
+ opt_edit_metadata_single_layout
+
+
+
+ -
+
+
+ Choose varying layouts in the Edit Metadata Single dialog.
+
+
+
+ -
+
+
+ Boolean columns are tristate:
+
+
+ opt_bools_are_tristate
+
+
+
+ -
+
+
+ If checked, boolean columns values can be Yes, No, and Unknown.
+If not checked, the values can be Yes and No.
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index 042899adbe..e560ac7c6e 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -213,6 +213,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
defs = self.prefs.defaults
defs['gui_restriction'] = defs['cs_restriction'] = ''
defs['categories_using_hierarchy'] = []
+ defs['edit_metadata_single_layout'] = 'default'
+ defs['bools_are_tristate'] = tweaks['bool_custom_columns_are_tristate']
# Migrate saved search and user categories to db preference scheme
def migrate_preference(key, default):
From c691f28a3833296ee6dd8424db02b0c4d4531bf3 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Fri, 8 Apr 2011 16:11:37 +0100
Subject: [PATCH 2/3] Change to use db.prefs bools_are_tristate
---
src/calibre/gui2/custom_column_widgets.py | 14 +++++++-------
src/calibre/gui2/library/delegates.py | 4 ++--
src/calibre/gui2/library/models.py | 4 ++--
src/calibre/gui2/preferences/columns.py | 6 +++++-
src/calibre/library/caches.py | 9 +++++----
src/calibre/library/server/content.py | 7 ++++---
6 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py
index 10602fb28c..81016d3c6a 100644
--- a/src/calibre/gui2/custom_column_widgets.py
+++ b/src/calibre/gui2/custom_column_widgets.py
@@ -62,7 +62,7 @@ class Bool(Base):
w = self.widgets[1]
items = [_('Yes'), _('No'), _('Undefined')]
icons = [I('ok.png'), I('list_remove.png'), I('blank.png')]
- if tweaks['bool_custom_columns_are_tristate'] == 'no':
+ if not self.db.prefs.get('bools_are_tristate'):
items = items[:-1]
icons = icons[:-1]
for icon, text in zip(icons, items):
@@ -70,7 +70,7 @@ class Bool(Base):
def setter(self, val):
val = {None: 2, False: 1, True: 0}[val]
- if tweaks['bool_custom_columns_are_tristate'] == 'no' and val == 2:
+ if not self.db.prefs.get('bools_are_tristate') and val == 2:
val = 1
self.widgets[1].setCurrentIndex(val)
@@ -549,7 +549,7 @@ class BulkBool(BulkBase, Bool):
value = None
for book_id in book_ids:
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
- if tweaks['bool_custom_columns_are_tristate'] == 'no' and val is None:
+ if not self.db.prefs.get('bools_are_tristate') and val is None:
val = False
if value is not None and value != val:
return None
@@ -559,7 +559,7 @@ class BulkBool(BulkBase, Bool):
def setup_ui(self, parent):
self.make_widgets(parent, QComboBox)
items = [_('Yes'), _('No')]
- if tweaks['bool_custom_columns_are_tristate'] == 'no':
+ if not self.db.prefs.get('bools_are_tristate'):
items.append('')
else:
items.append(_('Undefined'))
@@ -571,7 +571,7 @@ class BulkBool(BulkBase, Bool):
def getter(self):
val = self.main_widget.currentIndex()
- if tweaks['bool_custom_columns_are_tristate'] == 'no':
+ if not self.db.prefs.get('bools_are_tristate'):
return {2: False, 1: False, 0: True}[val]
else:
return {2: None, 1: False, 0: True}[val]
@@ -586,13 +586,13 @@ class BulkBool(BulkBase, Bool):
return
val = self.gui_val
val = self.normalize_ui_val(val)
- if tweaks['bool_custom_columns_are_tristate'] == 'no' and val is None:
+ if not self.db.prefs.get('bools_are_tristate') and val is None:
val = False
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
def a_c_checkbox_changed(self):
if not self.ignore_change_signals:
- if tweaks['bool_custom_columns_are_tristate'] == 'no' and \
+ if not self.db.prefs.get('bools_are_tristate') and \
self.main_widget.currentIndex() == 2:
self.a_c_checkbox.setChecked(False)
else:
diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py
index 0f74500099..ac8568af07 100644
--- a/src/calibre/gui2/library/delegates.py
+++ b/src/calibre/gui2/library/delegates.py
@@ -353,7 +353,7 @@ class CcBoolDelegate(QStyledItemDelegate): # {{{
editor = DelegateCB(parent)
items = [_('Y'), _('N'), ' ']
icons = [I('ok.png'), I('list_remove.png'), I('blank.png')]
- if tweaks['bool_custom_columns_are_tristate'] == 'no':
+ if not index.model().db.prefs.get('bools_are_tristate'):
items = items[:-1]
icons = icons[:-1]
for icon, text in zip(icons, items):
@@ -367,7 +367,7 @@ class CcBoolDelegate(QStyledItemDelegate): # {{{
def setEditorData(self, editor, index):
m = index.model()
val = m.db.data[index.row()][m.custom_columns[m.column_map[index.column()]]['rec_index']]
- if tweaks['bool_custom_columns_are_tristate'] == 'no':
+ if not m.db.prefs.get('bools_are_tristate'):
val = 1 if not val else 0
else:
val = 2 if val is None else 1 if not val else 0
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 3e1670c7af..653a8ea2f6 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -700,7 +700,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.dc_decorator[col] = functools.partial(
bool_type_decorator, idx=idx,
bool_cols_are_tristate=
- tweaks['bool_custom_columns_are_tristate'] != 'no')
+ self.db.prefs.get('bools_are_tristate'))
elif datatype in ('int', 'float'):
self.dc[col] = functools.partial(number_type, idx=idx)
elif datatype == 'datetime':
@@ -710,7 +710,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.dc_decorator[col] = functools.partial(
bool_type_decorator, idx=idx,
bool_cols_are_tristate=
- tweaks['bool_custom_columns_are_tristate'] != 'no')
+ self.db.prefs.get('bools_are_tristate'))
elif datatype == 'rating':
self.dc[col] = functools.partial(rating_type, idx=idx)
elif datatype == 'series':
diff --git a/src/calibre/gui2/preferences/columns.py b/src/calibre/gui2/preferences/columns.py
index 7c57054253..4079e2d3f4 100644
--- a/src/calibre/gui2/preferences/columns.py
+++ b/src/calibre/gui2/preferences/columns.py
@@ -38,7 +38,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r = self.register
choices = [(_('Default'), 'default'), (_('Compact Metadata'), 'alt1')]
r('edit_metadata_single_layout', db.prefs, choices=choices)
- r('bools_are_tristate', db.prefs)
+ r('bools_are_tristate', db.prefs, restart_required=True)
else:
self.items_in_v_eight.setVisible(False)
@@ -178,6 +178,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
must_restart = True
return must_restart
+ def refresh_gui(self, gui):
+ gui.library_view.reset()
+
+
if __name__ == '__main__':
from PyQt4.Qt import QApplication
diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py
index e5864ceaaf..74ddb2bc41 100644
--- a/src/calibre/library/caches.py
+++ b/src/calibre/library/caches.py
@@ -547,7 +547,7 @@ class ResultCache(SearchQueryParser): # {{{
return matchkind, query
def get_bool_matches(self, location, query, candidates):
- bools_are_tristate = tweaks['bool_custom_columns_are_tristate'] != 'no'
+ bools_are_tristate = not self.db_prefs.get('bools_are_tristate')
loc = self.field_metadata[location]['rec_index']
matches = set()
query = icu_lower(query)
@@ -947,7 +947,7 @@ class ResultCache(SearchQueryParser): # {{{
if not fields:
fields = [('timestamp', False)]
- keyg = SortKeyGenerator(fields, self.field_metadata, self._data)
+ keyg = SortKeyGenerator(fields, self.field_metadata, self._data, self.db_prefs)
self._map.sort(key=keyg)
tmap = list(itertools.repeat(False, len(self._data)))
@@ -970,9 +970,10 @@ class SortKey(object):
class SortKeyGenerator(object):
- def __init__(self, fields, field_metadata, data):
+ def __init__(self, fields, field_metadata, data, db_prefs):
from calibre.utils.icu import sort_key
self.field_metadata = field_metadata
+ self.db_prefs = db_prefs
self.orders = [1 if x[1] else -1 for x in fields]
self.entries = [(x[0], field_metadata[x[0]]) for x in fields]
self.library_order = tweaks['title_series_sorting'] == 'library_order'
@@ -1032,7 +1033,7 @@ class SortKeyGenerator(object):
val = self.string_sort_key(val)
elif dt == 'bool':
- if tweaks['bool_custom_columns_are_tristate'] == 'no':
+ if not self.db_prefs.get('bools_are_tristate'):
val = {True: 1, False: 2, None: 2}.get(val, 2)
else:
val = {True: 1, False: 2, None: 3}.get(val, 3)
diff --git a/src/calibre/library/server/content.py b/src/calibre/library/server/content.py
index 919f5a7969..0c3edd1627 100644
--- a/src/calibre/library/server/content.py
+++ b/src/calibre/library/server/content.py
@@ -17,8 +17,8 @@ from calibre.utils.magick.draw import save_cover_data_to, Image, \
class CSSortKeyGenerator(SortKeyGenerator):
- def __init__(self, fields, fm):
- SortKeyGenerator.__init__(self, fields, fm, None)
+ def __init__(self, fields, fm, db_prefs):
+ SortKeyGenerator.__init__(self, fields, fm, None, db_prefs)
def __call__(self, record):
return self.itervals(record).next()
@@ -56,7 +56,8 @@ class ContentServer(object):
field = self.db.data.sanitize_sort_field_name(field)
if field not in self.db.field_metadata.sortable_field_keys():
raise cherrypy.HTTPError(400, '%s is not a valid sort field'%field)
- keyg = CSSortKeyGenerator([(field, order)], self.db.field_metadata)
+ keyg = CSSortKeyGenerator([(field, order)], self.db.field_metadata,
+ self.db.prefs)
items.sort(key=keyg, reverse=not order)
# }}}
From 985d2f101b37cda64b875210b4d26547626d67bb Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Fri, 8 Apr 2011 16:29:17 +0100
Subject: [PATCH 3/3] ...
---
src/calibre/library/database2.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index e560ac7c6e..ccc5b60427 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -40,7 +40,7 @@ from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
from calibre.utils.magick.draw import save_cover_data_to
from calibre.utils.recycle_bin import delete_file, delete_tree
from calibre.utils.formatter_functions import load_user_template_functions
-
+from calibre.utils.config import test_eight_code
copyfile = os.link if hasattr(os, 'link') else shutil.copyfile
@@ -214,7 +214,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
defs['gui_restriction'] = defs['cs_restriction'] = ''
defs['categories_using_hierarchy'] = []
defs['edit_metadata_single_layout'] = 'default'
- defs['bools_are_tristate'] = tweaks['bool_custom_columns_are_tristate']
+
+ defs['bools_are_tristate'] = \
+ tweaks.get('bool_custom_columns_are_tristate', 'yes') == 'yes'
+ if self.prefs.get('bools_are_tristate') is None or not test_eight_code:
+ self.prefs.set('bools_are_tristate', defs['bools_are_tristate'])
# Migrate saved search and user categories to db preference scheme
def migrate_preference(key, default):