Change composites to use the cache correctly, so that searches & sorts used. In the process, remove the metadata cache from models.py.

Fix some bugs introduced by composite columns:
1) no edit widget in bulk_metadata edit
2) explicitly do not make a delegate in views.py
This commit is contained in:
Charles Haley 2010-09-18 13:45:01 +01:00
parent 83fc5b2cc0
commit c59545a96a
5 changed files with 31 additions and 33 deletions

View File

@ -348,6 +348,8 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
ans = [] ans = []
column = row = comments_row = 0 column = row = comments_row = 0
for col in cols: for col in cols:
if not x[col]['editable']:
continue
dt = x[col]['datatype'] dt = x[col]['datatype']
if dt == 'comments': if dt == 'comments':
continue continue

View File

@ -86,7 +86,6 @@ class BooksModel(QAbstractTableModel): # {{{
self.last_search = '' # The last search performed on this model self.last_search = '' # The last search performed on this model
self.column_map = [] self.column_map = []
self.headers = {} self.headers = {}
self.metadata_cache = {}
self.alignment_map = {} self.alignment_map = {}
self.buffer_size = buffer self.buffer_size = buffer
self.cover_cache = None self.cover_cache = None
@ -115,16 +114,6 @@ class BooksModel(QAbstractTableModel): # {{{
def clear_caches(self): def clear_caches(self):
if self.cover_cache: if self.cover_cache:
self.cover_cache.clear_cache() self.cover_cache.clear_cache()
self.metadata_cache = {}
def get_cached_metadata(self, idx):
if idx not in self.metadata_cache:
self.metadata_cache[idx] = self.db.get_metadata(idx)
return self.metadata_cache[idx]
def remove_cached_metadata(self, idx):
if idx in self.metadata_cache:
del self.metadata_cache[idx]
def read_config(self): def read_config(self):
self.use_roman_numbers = config['use_roman_numerals_for_series_number'] self.use_roman_numbers = config['use_roman_numerals_for_series_number']
@ -157,7 +146,6 @@ class BooksModel(QAbstractTableModel): # {{{
elif col in self.custom_columns: elif col in self.custom_columns:
self.headers[col] = self.custom_columns[col]['name'] self.headers[col] = self.custom_columns[col]['name']
self.metadata_cache = {}
self.build_data_convertors() self.build_data_convertors()
self.reset() self.reset()
self.database_changed.emit(db) self.database_changed.emit(db)
@ -171,13 +159,11 @@ class BooksModel(QAbstractTableModel): # {{{
db.add_listener(refresh_cover) db.add_listener(refresh_cover)
def refresh_ids(self, ids, current_row=-1): def refresh_ids(self, ids, current_row=-1):
self.metadata_cache = {}
rows = self.db.refresh_ids(ids) rows = self.db.refresh_ids(ids)
if rows: if rows:
self.refresh_rows(rows, current_row=current_row) self.refresh_rows(rows, current_row=current_row)
def refresh_rows(self, rows, current_row=-1): def refresh_rows(self, rows, current_row=-1):
self.metadata_cache = {}
for row in rows: for row in rows:
if row == current_row: if row == current_row:
self.new_bookdisplay_data.emit( self.new_bookdisplay_data.emit(
@ -207,7 +193,6 @@ class BooksModel(QAbstractTableModel): # {{{
return ret return ret
def count_changed(self, *args): def count_changed(self, *args):
self.metadata_cache = {}
self.count_changed_signal.emit(self.db.count()) self.count_changed_signal.emit(self.db.count())
def row_indices(self, index): def row_indices(self, index):
@ -277,7 +262,6 @@ class BooksModel(QAbstractTableModel): # {{{
self.sorting_done.emit(self.db.index) self.sorting_done.emit(self.db.index)
def refresh(self, reset=True): def refresh(self, reset=True):
self.metadata_cache = {}
self.db.refresh(field=None) self.db.refresh(field=None)
self.resort(reset=reset) self.resort(reset=reset)
@ -334,7 +318,7 @@ class BooksModel(QAbstractTableModel): # {{{
data[_('Series')] = \ data[_('Series')] = \
_('Book <font face="serif">%s</font> of %s.')%\ _('Book <font face="serif">%s</font> of %s.')%\
(sidx, prepare_string_for_xml(series)) (sidx, prepare_string_for_xml(series))
mi = self.get_cached_metadata(idx) mi = self.db.get_metadata(idx)
for key in mi.user_metadata_keys: for key in mi.user_metadata_keys:
name, val = mi.format_field(key) name, val = mi.format_field(key)
if val is not None: if val is not None:
@ -343,7 +327,6 @@ class BooksModel(QAbstractTableModel): # {{{
def set_cache(self, idx): def set_cache(self, idx):
l, r = 0, self.count()-1 l, r = 0, self.count()-1
self.remove_cached_metadata(idx)
if self.cover_cache is not None: if self.cover_cache is not None:
l = max(l, idx-self.buffer_size) l = max(l, idx-self.buffer_size)
r = min(r, idx+self.buffer_size) r = min(r, idx+self.buffer_size)
@ -603,10 +586,6 @@ class BooksModel(QAbstractTableModel): # {{{
def number_type(r, idx=-1): def number_type(r, idx=-1):
return QVariant(self.db.data[r][idx]) return QVariant(self.db.data[r][idx])
def composite_type(r, key=None):
mi = self.get_cached_metadata(r)
return QVariant(mi.get(key, ''))
self.dc = { self.dc = {
'title' : functools.partial(text_type, 'title' : functools.partial(text_type,
idx=self.db.field_metadata['title']['rec_index'], mult=False), idx=self.db.field_metadata['title']['rec_index'], mult=False),
@ -640,7 +619,7 @@ class BooksModel(QAbstractTableModel): # {{{
for col in self.custom_columns: for col in self.custom_columns:
idx = self.custom_columns[col]['rec_index'] idx = self.custom_columns[col]['rec_index']
datatype = self.custom_columns[col]['datatype'] datatype = self.custom_columns[col]['datatype']
if datatype in ('text', 'comments'): if datatype in ('text', 'comments', 'composite'):
self.dc[col] = functools.partial(text_type, idx=idx, self.dc[col] = functools.partial(text_type, idx=idx,
mult=self.custom_columns[col]['is_multiple']) mult=self.custom_columns[col]['is_multiple'])
elif datatype in ('int', 'float'): elif datatype in ('int', 'float'):
@ -657,8 +636,6 @@ class BooksModel(QAbstractTableModel): # {{{
elif datatype == 'series': elif datatype == 'series':
self.dc[col] = functools.partial(series_type, idx=idx, self.dc[col] = functools.partial(series_type, idx=idx,
siix=self.db.field_metadata.cc_series_index_column_for(col)) siix=self.db.field_metadata.cc_series_index_column_for(col))
elif datatype == 'composite':
self.dc[col] = functools.partial(composite_type, key=col)
else: else:
print 'What type is this?', col, datatype print 'What type is this?', col, datatype
# build a index column to data converter map, to remove the string lookup in the data loop # build a index column to data converter map, to remove the string lookup in the data loop
@ -753,7 +730,6 @@ class BooksModel(QAbstractTableModel): # {{{
if role == Qt.EditRole: if role == Qt.EditRole:
row, col = index.row(), index.column() row, col = index.row(), index.column()
column = self.column_map[col] column = self.column_map[col]
self.remove_cached_metadata(row)
if self.is_custom_column(column): if self.is_custom_column(column):
if not self.set_custom_column_data(row, column, value): if not self.set_custom_column_data(row, column, value):
return False return False

View File

@ -391,6 +391,9 @@ class BooksView(QTableView): # {{{
self.setItemDelegateForColumn(cm.index(colhead), self.cc_bool_delegate) self.setItemDelegateForColumn(cm.index(colhead), self.cc_bool_delegate)
elif cc['datatype'] == 'rating': elif cc['datatype'] == 'rating':
self.setItemDelegateForColumn(cm.index(colhead), self.rating_delegate) self.setItemDelegateForColumn(cm.index(colhead), self.rating_delegate)
elif cc['datatype'] == 'composite':
pass
# no delegate for composite columns, as they are not editable
else: else:
dattr = colhead+'_delegate' dattr = colhead+'_delegate'
delegate = colhead if hasattr(self, dattr) else 'text' delegate = colhead if hasattr(self, dattr) else 'text'

View File

@ -121,6 +121,11 @@ class ResultCache(SearchQueryParser):
self.build_date_relop_dict() self.build_date_relop_dict()
self.build_numeric_relop_dict() self.build_numeric_relop_dict()
self.composites = []
for key in field_metadata:
if field_metadata[key]['datatype'] == 'composite':
self.composites.append((key, 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]]
@ -372,7 +377,7 @@ class ResultCache(SearchQueryParser):
if len(self.field_metadata[x]['search_terms']): if len(self.field_metadata[x]['search_terms']):
db_col[x] = self.field_metadata[x]['rec_index'] db_col[x] = self.field_metadata[x]['rec_index']
if self.field_metadata[x]['datatype'] not in \ if self.field_metadata[x]['datatype'] not in \
['text', 'comments', 'series']: ['composite', 'text', 'comments', 'series']:
exclude_fields.append(db_col[x]) exclude_fields.append(db_col[x])
col_datatype[db_col[x]] = self.field_metadata[x]['datatype'] col_datatype[db_col[x]] = self.field_metadata[x]['datatype']
is_multiple_cols[db_col[x]] = self.field_metadata[x]['is_multiple'] is_multiple_cols[db_col[x]] = self.field_metadata[x]['is_multiple']
@ -534,6 +539,10 @@ class ResultCache(SearchQueryParser):
self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0] self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]
self._data[id].append(db.has_cover(id, index_is_id=True)) self._data[id].append(db.has_cover(id, index_is_id=True))
self._data[id].append(db.book_on_device_string(id)) self._data[id].append(db.book_on_device_string(id))
if len(self.composites) > 0:
mi = db.get_metadata(id, index_is_id=True)
for k,c in self.composites:
self._data[id][c] = mi.format_field(k)[1]
except IndexError: except IndexError:
return None return None
try: try:
@ -550,6 +559,10 @@ class ResultCache(SearchQueryParser):
self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0] self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]
self._data[id].append(db.has_cover(id, index_is_id=True)) self._data[id].append(db.has_cover(id, index_is_id=True))
self._data[id].append(db.book_on_device_string(id)) self._data[id].append(db.book_on_device_string(id))
if len(self.composites) > 0:
mi = db.get_metadata(id, index_is_id=True)
for k,c in self.composites:
self._data[id][c] = mi.format_field(k)[1]
self._map[0:0] = ids self._map[0:0] = ids
self._map_filtered[0:0] = ids self._map_filtered[0:0] = ids
@ -575,6 +588,11 @@ class ResultCache(SearchQueryParser):
if item is not None: if item is not None:
item.append(db.has_cover(item[0], index_is_id=True)) item.append(db.has_cover(item[0], index_is_id=True))
item.append(db.book_on_device_string(item[0])) item.append(db.book_on_device_string(item[0]))
if len(self.composites) > 0:
mi = db.get_metadata(item[0], index_is_id=True)
for k,c in self.composites:
item[c] = mi.format_field(k)[1]
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:
self.sort(field, ascending) self.sort(field, ascending)

View File

@ -323,12 +323,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.has_id = self.data.has_id self.has_id = self.data.has_id
self.count = self.data.count self.count = self.data.count
self.refresh_ondevice = functools.partial(self.data.refresh_ondevice, self)
self.refresh()
self.last_update_check = self.last_modified()
for prop in ('author_sort', 'authors', 'comment', 'comments', 'isbn', for prop in ('author_sort', 'authors', 'comment', 'comments', 'isbn',
'publisher', 'rating', 'series', 'series_index', 'tags', 'publisher', 'rating', 'series', 'series_index', 'tags',
'title', 'timestamp', 'uuid', 'pubdate', 'ondevice'): 'title', 'timestamp', 'uuid', 'pubdate', 'ondevice'):
@ -337,6 +331,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
setattr(self, 'title_sort', functools.partial(self.get_property, setattr(self, 'title_sort', functools.partial(self.get_property,
loc=self.FIELD_MAP['sort'])) loc=self.FIELD_MAP['sort']))
self.refresh_ondevice = functools.partial(self.data.refresh_ondevice, self)
self.refresh()
self.last_update_check = self.last_modified()
def initialize_database(self): def initialize_database(self):
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read() metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
self.conn.executescript(metadata_sqlite) self.conn.executescript(metadata_sqlite)