mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
enums now always have None. Significant speed increasing when recomputing author sort values
This commit is contained in:
commit
3be66119d0
@ -318,16 +318,14 @@ class Enumeration(Base):
|
|||||||
QComboBox(parent)]
|
QComboBox(parent)]
|
||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
vals = self.col_metadata['display']['enum_values']
|
vals = self.col_metadata['display']['enum_values']
|
||||||
|
w.addItem('')
|
||||||
for v in vals:
|
for v in vals:
|
||||||
w.addItem(v)
|
w.addItem(v)
|
||||||
|
|
||||||
def initialize(self, book_id):
|
def initialize(self, book_id):
|
||||||
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||||
if val is None:
|
|
||||||
# This really shouldn't happen
|
|
||||||
val = self.col_metadata['display']['enum_values'][0]
|
|
||||||
self.initial_val = val
|
|
||||||
val = self.normalize_db_val(val)
|
val = self.normalize_db_val(val)
|
||||||
|
self.initial_val = val
|
||||||
idx = self.widgets[1].findText(val)
|
idx = self.widgets[1].findText(val)
|
||||||
if idx < 0:
|
if idx < 0:
|
||||||
error_dialog(self.parent, '',
|
error_dialog(self.parent, '',
|
||||||
@ -340,13 +338,21 @@ class Enumeration(Base):
|
|||||||
self.widgets[1].setCurrentIndex(idx)
|
self.widgets[1].setCurrentIndex(idx)
|
||||||
|
|
||||||
def setter(self, val):
|
def setter(self, val):
|
||||||
if val is None:
|
|
||||||
val = ''
|
|
||||||
self.widgets[1].setCurrentIndex(self.widgets[1].findText(val))
|
self.widgets[1].setCurrentIndex(self.widgets[1].findText(val))
|
||||||
|
|
||||||
def getter(self):
|
def getter(self):
|
||||||
return unicode(self.widgets[1].currentText())
|
return unicode(self.widgets[1].currentText())
|
||||||
|
|
||||||
|
def normalize_db_val(self, val):
|
||||||
|
if val is None:
|
||||||
|
val = ''
|
||||||
|
return val
|
||||||
|
|
||||||
|
def normalize_ui_val(self, val):
|
||||||
|
if not val:
|
||||||
|
val = None
|
||||||
|
return val
|
||||||
|
|
||||||
widgets = {
|
widgets = {
|
||||||
'bool' : Bool,
|
'bool' : Bool,
|
||||||
'rating' : Rating,
|
'rating' : Rating,
|
||||||
@ -597,7 +603,7 @@ class BulkEnumeration(BulkBase, Enumeration):
|
|||||||
dialog_shown = False
|
dialog_shown = False
|
||||||
for book_id in book_ids:
|
for book_id in book_ids:
|
||||||
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||||
if val not in self.col_metadata['display']['enum_values']:
|
if val and val not in self.col_metadata['display']['enum_values']:
|
||||||
if not dialog_shown:
|
if not dialog_shown:
|
||||||
error_dialog(self.parent, '',
|
error_dialog(self.parent, '',
|
||||||
_('The enumeration "{0}" contains invalid values '
|
_('The enumeration "{0}" contains invalid values '
|
||||||
@ -620,6 +626,7 @@ class BulkEnumeration(BulkBase, Enumeration):
|
|||||||
w = self.widgets[1]
|
w = self.widgets[1]
|
||||||
vals = self.col_metadata['display']['enum_values']
|
vals = self.col_metadata['display']['enum_values']
|
||||||
w.addItem('Do Not Change')
|
w.addItem('Do Not Change')
|
||||||
|
w.addItem('')
|
||||||
for v in vals:
|
for v in vals:
|
||||||
w.addItem(v)
|
w.addItem(v)
|
||||||
|
|
||||||
@ -632,7 +639,10 @@ class BulkEnumeration(BulkBase, Enumeration):
|
|||||||
if val == ' nochange ':
|
if val == ' nochange ':
|
||||||
self.widgets[1].setCurrentIndex(0)
|
self.widgets[1].setCurrentIndex(0)
|
||||||
else:
|
else:
|
||||||
self.widgets[1].setCurrentIndex(self.widgets[1].findText(val))
|
if val is None:
|
||||||
|
self.widgets[1].setCurrentIndex(1)
|
||||||
|
else:
|
||||||
|
self.widgets[1].setCurrentIndex(self.widgets[1].findText(val))
|
||||||
|
|
||||||
def commit(self, book_ids, notify=False):
|
def commit(self, book_ids, notify=False):
|
||||||
val = self.gui_val
|
val = self.gui_val
|
||||||
@ -640,12 +650,6 @@ class BulkEnumeration(BulkBase, Enumeration):
|
|||||||
if val != self.initial_val and val != ' nochange ':
|
if val != self.initial_val and val != ' nochange ':
|
||||||
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
|
self.db.set_custom_bulk(book_ids, val, num=self.col_id, notify=notify)
|
||||||
|
|
||||||
def normalize_db_val(self, val):
|
|
||||||
if val is None:
|
|
||||||
# this really shouldn't happen
|
|
||||||
val = self.col_metadata['display']['enum_values'][0]
|
|
||||||
return val
|
|
||||||
|
|
||||||
class RemoveTags(QWidget):
|
class RemoveTags(QWidget):
|
||||||
|
|
||||||
def __init__(self, parent, values):
|
def __init__(self, parent, values):
|
||||||
|
@ -263,28 +263,22 @@ class CcEnumDelegate(QStyledItemDelegate): # {{{
|
|||||||
m = index.model()
|
m = index.model()
|
||||||
col = m.column_map[index.column()]
|
col = m.column_map[index.column()]
|
||||||
editor = QComboBox(parent)
|
editor = QComboBox(parent)
|
||||||
|
editor.addItem('')
|
||||||
for v in m.custom_columns[col]['display']['enum_values']:
|
for v in m.custom_columns[col]['display']['enum_values']:
|
||||||
editor.addItem(v)
|
editor.addItem(v)
|
||||||
return editor
|
return editor
|
||||||
|
|
||||||
def setModelData(self, editor, model, index):
|
def setModelData(self, editor, model, index):
|
||||||
val = unicode(editor.currentText())
|
val = unicode(editor.currentText())
|
||||||
m = index.model()
|
if not val:
|
||||||
col = m.column_map[index.column()]
|
val = None
|
||||||
if val not in m.custom_columns[col]['display']['enum_values']:
|
|
||||||
# This shouldn't happen ...
|
|
||||||
print 'shouldnt happen'
|
|
||||||
val = m.custom_columns[col]['display']['enum_values'][0]
|
|
||||||
model.setData(index, QVariant(val), Qt.EditRole)
|
model.setData(index, QVariant(val), Qt.EditRole)
|
||||||
|
|
||||||
def setEditorData(self, editor, index):
|
def setEditorData(self, editor, index):
|
||||||
m = index.model()
|
m = index.model()
|
||||||
val = m.db.data[index.row()][m.custom_columns[m.column_map[index.column()]]['rec_index']]
|
val = m.db.data[index.row()][m.custom_columns[m.column_map[index.column()]]['rec_index']]
|
||||||
if val is None:
|
if val is None:
|
||||||
# This shouldn't happen
|
val = ''
|
||||||
m = index.model()
|
|
||||||
col = m.column_map[index.column()]
|
|
||||||
val = m.custom_columns[col]['display']['enum_values'][0]
|
|
||||||
idx = editor.findText(val)
|
idx = editor.findText(val)
|
||||||
if idx < 0:
|
if idx < 0:
|
||||||
editor.setCurrentIndex(0)
|
editor.setCurrentIndex(0)
|
||||||
|
@ -724,6 +724,8 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
val = val if val else None
|
val = val if val else None
|
||||||
elif typ == 'enumeration':
|
elif typ == 'enumeration':
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value.toString()).strip()
|
||||||
|
if not val:
|
||||||
|
val = None
|
||||||
elif typ == 'bool':
|
elif typ == 'bool':
|
||||||
val = value.toPyObject()
|
val = value.toPyObject()
|
||||||
elif typ == 'rating':
|
elif typ == 'rating':
|
||||||
@ -732,7 +734,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
val *= 2
|
val *= 2
|
||||||
elif typ in ('int', 'float'):
|
elif typ in ('int', 'float'):
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value.toString()).strip()
|
||||||
if val is None or not val:
|
if not val:
|
||||||
val = None
|
val = None
|
||||||
elif typ == 'datetime':
|
elif typ == 'datetime':
|
||||||
val = value.toDate()
|
val = value.toDate()
|
||||||
|
@ -167,6 +167,10 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
|||||||
return self.simple_error('', _('You must enter at least one'
|
return self.simple_error('', _('You must enter at least one'
|
||||||
' value for enumeration columns'))
|
' value for enumeration columns'))
|
||||||
l = [v.strip() for v in unicode(self.enum_box.text()).split(',')]
|
l = [v.strip() for v in unicode(self.enum_box.text()).split(',')]
|
||||||
|
for v in l:
|
||||||
|
if not v:
|
||||||
|
return self.simple_error('', _('You cannot provide the empty '
|
||||||
|
'value, as it is included by default'))
|
||||||
for i in range(0, len(l)-1):
|
for i in range(0, len(l)-1):
|
||||||
if l[i] in l[i+1:]:
|
if l[i] in l[i+1:]:
|
||||||
return self.simple_error('', _('The value "{0}" is in the '
|
return self.simple_error('', _('The value "{0}" is in the '
|
||||||
|
@ -212,10 +212,9 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="enum_box">
|
<widget class="QLineEdit" name="enum_box">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>A comma-separated list of permitted values. You can specify
|
<string>A comma-separated list of permitted values. The empty value is always
|
||||||
empty values by entering only the comma. For example, the list
|
included, and is the default. For example, the list 'one,two,three' has
|
||||||
',one,two,three' has 4 valid values, one of them empty. The first
|
four values, the first of them being the empty value.</string>
|
||||||
value in the list is the default.</string>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
@ -231,7 +230,7 @@ value in the list is the default.</string>
|
|||||||
<string>Default: (nothing)</string>
|
<string>Default: (nothing)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>The first value entered will be the default value for this enumeration</string>
|
<string>The empty string is always the first value</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -106,10 +106,13 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.refresh_required.connect(self.recount, type=Qt.QueuedConnection)
|
self.refresh_required.connect(self.recount, type=Qt.QueuedConnection)
|
||||||
self.sort_by.currentIndexChanged.connect(self.sort_changed)
|
self.sort_by.currentIndexChanged.connect(self.sort_changed)
|
||||||
self.made_connections = True
|
self.made_connections = True
|
||||||
|
self.refresh_signal_processed = True
|
||||||
db.add_listener(self.database_changed)
|
db.add_listener(self.database_changed)
|
||||||
|
|
||||||
def database_changed(self, event, ids):
|
def database_changed(self, event, ids):
|
||||||
self.refresh_required.emit()
|
if self.refresh_signal_processed:
|
||||||
|
self.refresh_signal_processed = False
|
||||||
|
self.refresh_required.emit()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def match_all(self):
|
def match_all(self):
|
||||||
@ -295,6 +298,7 @@ class TagsView(QTreeView): # {{{
|
|||||||
return self.isExpanded(idx)
|
return self.isExpanded(idx)
|
||||||
|
|
||||||
def recount(self, *args):
|
def recount(self, *args):
|
||||||
|
self.refresh_signal_processed = True
|
||||||
ci = self.currentIndex()
|
ci = self.currentIndex()
|
||||||
if not ci.isValid():
|
if not ci.isValid():
|
||||||
ci = self.indexAt(QPoint(10, 10))
|
ci = self.indexAt(QPoint(10, 10))
|
||||||
@ -937,7 +941,9 @@ class TagBrowserMixin(object): # {{{
|
|||||||
if old_author != new_author:
|
if old_author != new_author:
|
||||||
# The id might change if the new author already exists
|
# The id might change if the new author already exists
|
||||||
id = db.rename_author(id, new_author)
|
id = db.rename_author(id, new_author)
|
||||||
db.set_sort_field_for_author(id, unicode(new_sort))
|
db.set_sort_field_for_author(id, unicode(new_sort),
|
||||||
|
commit=False, notify=False)
|
||||||
|
db.commit()
|
||||||
self.library_view.model().refresh()
|
self.library_view.model().refresh()
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
|
|
||||||
|
@ -254,12 +254,6 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
if field_metadata[key]['datatype'] == 'composite':
|
if field_metadata[key]['datatype'] == 'composite':
|
||||||
self.composites.append((key, field_metadata[key]['rec_index']))
|
self.composites.append((key, field_metadata[key]['rec_index']))
|
||||||
|
|
||||||
self.enumerations = []
|
|
||||||
for key in field_metadata:
|
|
||||||
if field_metadata[key]['datatype'] == 'enumeration':
|
|
||||||
self.enumerations.append((field_metadata[key]['display']['enum_values'][0],
|
|
||||||
field_metadata[key]['rec_index']))
|
|
||||||
|
|
||||||
def __getitem__(self, row):
|
def __getitem__(self, row):
|
||||||
return self._data[self._map_filtered[row]]
|
return self._data[self._map_filtered[row]]
|
||||||
|
|
||||||
@ -697,10 +691,6 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
mi = db.get_metadata(id, index_is_id=True)
|
mi = db.get_metadata(id, index_is_id=True)
|
||||||
for k,c in self.composites:
|
for k,c in self.composites:
|
||||||
self._data[id][c] = mi.get(k, None)
|
self._data[id][c] = mi.get(k, None)
|
||||||
if len(self.enumerations) > 0:
|
|
||||||
for v,c in self.enumerations:
|
|
||||||
if self._data[id][c] is None:
|
|
||||||
self._data[id][c] = v
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
@ -721,10 +711,6 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
mi = db.get_metadata(id, index_is_id=True)
|
mi = db.get_metadata(id, index_is_id=True)
|
||||||
for k,c in self.composites:
|
for k,c in self.composites:
|
||||||
self._data[id][c] = mi.get(k)
|
self._data[id][c] = mi.get(k)
|
||||||
if len(self.enumerations) > 0:
|
|
||||||
for v,c in self.self._data[id][c]:
|
|
||||||
if self._data[id][c] is None:
|
|
||||||
self._data[id][c] = v
|
|
||||||
self._map[0:0] = ids
|
self._map[0:0] = ids
|
||||||
self._map_filtered[0:0] = ids
|
self._map_filtered[0:0] = ids
|
||||||
|
|
||||||
@ -754,10 +740,6 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
mi = db.get_metadata(item[0], index_is_id=True)
|
mi = db.get_metadata(item[0], index_is_id=True)
|
||||||
for k,c in self.composites:
|
for k,c in self.composites:
|
||||||
item[c] = mi.get(k)
|
item[c] = mi.get(k)
|
||||||
if len(self.enumerations) > 0:
|
|
||||||
for v,c in self.enumerations:
|
|
||||||
if item[c] is None:
|
|
||||||
item[c] = v
|
|
||||||
|
|
||||||
self._map = [i[0] for i in self._data if i is not None]
|
self._map = [i[0] for i in self._data if i is not None]
|
||||||
if field is not None:
|
if field is not None:
|
||||||
|
@ -136,6 +136,12 @@ class CustomColumns(object):
|
|||||||
x = bool(int(x))
|
x = bool(int(x))
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
def adapt_enum(x, d):
|
||||||
|
v = adapt_text(x, d)
|
||||||
|
if not v:
|
||||||
|
v = None
|
||||||
|
return v
|
||||||
|
|
||||||
self.custom_data_adapters = {
|
self.custom_data_adapters = {
|
||||||
'float': lambda x,d : x if x is None else float(x),
|
'float': lambda x,d : x if x is None else float(x),
|
||||||
'int': lambda x,d : x if x is None else int(x),
|
'int': lambda x,d : x if x is None else int(x),
|
||||||
@ -145,7 +151,7 @@ class CustomColumns(object):
|
|||||||
'datetime' : adapt_datetime,
|
'datetime' : adapt_datetime,
|
||||||
'text':adapt_text,
|
'text':adapt_text,
|
||||||
'series':adapt_text,
|
'series':adapt_text,
|
||||||
'enumeration': adapt_text
|
'enumeration': adapt_enum
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create Tag Browser categories for custom columns
|
# Create Tag Browser categories for custom columns
|
||||||
@ -177,8 +183,6 @@ class CustomColumns(object):
|
|||||||
ans = ans.split('|') if ans else []
|
ans = ans.split('|') if ans else []
|
||||||
if data['display'].get('sort_alpha', False):
|
if data['display'].get('sort_alpha', False):
|
||||||
ans.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
|
ans.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
|
||||||
elif data['datatype'] == 'enumeration' and ans is None:
|
|
||||||
ans = data['display']['enum_values'][0]
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def get_custom_extra(self, idx, label=None, num=None, index_is_id=False):
|
def get_custom_extra(self, idx, label=None, num=None, index_is_id=False):
|
||||||
@ -442,8 +446,8 @@ class CustomColumns(object):
|
|||||||
val = self.custom_data_adapters[data['datatype']](val, data)
|
val = self.custom_data_adapters[data['datatype']](val, data)
|
||||||
|
|
||||||
if data['normalized']:
|
if data['normalized']:
|
||||||
if data['datatype'] == 'enumeration' and \
|
if data['datatype'] == 'enumeration' and (
|
||||||
val not in data['display']['enum_values']:
|
val and val not in data['display']['enum_values']):
|
||||||
return None
|
return None
|
||||||
if not append or not data['is_multiple']:
|
if not append or not data['is_multiple']:
|
||||||
self.conn.execute('DELETE FROM %s WHERE book=?'%lt, (id_,))
|
self.conn.execute('DELETE FROM %s WHERE book=?'%lt, (id_,))
|
||||||
|
@ -1639,15 +1639,16 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
return []
|
return []
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def set_sort_field_for_author(self, old_id, new_sort):
|
def set_sort_field_for_author(self, old_id, new_sort, commit=True, notify=False):
|
||||||
self.conn.execute('UPDATE authors SET sort=? WHERE id=?', \
|
self.conn.execute('UPDATE authors SET sort=? WHERE id=?', \
|
||||||
(new_sort.strip(), old_id))
|
(new_sort.strip(), old_id))
|
||||||
self.conn.commit()
|
if commit:
|
||||||
|
self.conn.commit()
|
||||||
# Now change all the author_sort fields in books by this author
|
# Now change all the author_sort fields in books by this author
|
||||||
bks = self.conn.get('SELECT book from books_authors_link WHERE author=?', (old_id,))
|
bks = self.conn.get('SELECT book from books_authors_link WHERE author=?', (old_id,))
|
||||||
for (book_id,) in bks:
|
for (book_id,) in bks:
|
||||||
ss = self.author_sort_from_book(book_id, index_is_id=True)
|
ss = self.author_sort_from_book(book_id, index_is_id=True)
|
||||||
self.set_author_sort(book_id, ss)
|
self.set_author_sort(book_id, ss, notify=notify, commit=commit)
|
||||||
|
|
||||||
def rename_author(self, old_id, new_name):
|
def rename_author(self, old_id, new_name):
|
||||||
# Make sure that any commas in new_name are changed to '|'!
|
# Make sure that any commas in new_name are changed to '|'!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user